[clang] [clang][bytecode] Slightly optimize integral casts of literals (PR #138879)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Thu May 8 04:03:28 PDT 2025
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/138879
>From c06949b212d3ce4a09bb978d1e5eceb4f4a1b1f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 6 May 2025 16:37:34 +0200
Subject: [PATCH] We often see initializers like
unsigned a = 10;
which take an integer literal and immediately cast it to another type.
Recognize this pattern and omit the cast, simply emitting the value as a different type directly.
Also, switch classifyPrim() when it's possible and use castAs() instead
of getAs() when we know the type is a MemberPointerType.
---
clang/lib/AST/ByteCode/Compiler.cpp | 107 ++++++++++++++++------------
1 file changed, 61 insertions(+), 46 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index ae6574cf99159..6151028ff327b 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -238,8 +238,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_DerivedToBaseMemberPointer: {
assert(classifyPrim(CE->getType()) == PT_MemberPtr);
assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr);
- const auto *FromMP = SubExpr->getType()->getAs<MemberPointerType>();
- const auto *ToMP = CE->getType()->getAs<MemberPointerType>();
+ const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();
+ const auto *ToMP = CE->getType()->castAs<MemberPointerType>();
unsigned DerivedOffset =
Ctx.collectBaseOffset(ToMP->getMostRecentCXXRecordDecl(),
@@ -254,8 +254,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_BaseToDerivedMemberPointer: {
assert(classifyPrim(CE) == PT_MemberPtr);
assert(classifyPrim(SubExpr) == PT_MemberPtr);
- const auto *FromMP = SubExpr->getType()->getAs<MemberPointerType>();
- const auto *ToMP = CE->getType()->getAs<MemberPointerType>();
+ const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();
+ const auto *ToMP = CE->getType()->castAs<MemberPointerType>();
unsigned DerivedOffset =
Ctx.collectBaseOffset(FromMP->getMostRecentCXXRecordDecl(),
@@ -320,29 +320,30 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
}
case CK_IntegralToFloating: {
- std::optional<PrimType> FromT = classify(SubExpr->getType());
- if (!FromT)
+ if (!CE->getType()->isRealFloatingType())
return false;
-
if (!this->visit(SubExpr))
return false;
-
const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
- return this->emitCastIntegralFloating(*FromT, TargetSemantics,
- getFPOptions(CE), CE);
+ return this->emitCastIntegralFloating(
+ classifyPrim(SubExpr), TargetSemantics, getFPOptions(CE), CE);
}
- case CK_FloatingToBoolean:
- case CK_FloatingToIntegral: {
-
- std::optional<PrimType> ToT = classify(CE->getType());
-
- if (!ToT)
+ case CK_FloatingToBoolean: {
+ if (!SubExpr->getType()->isRealFloatingType() ||
+ !CE->getType()->isBooleanType())
return false;
-
+ if (const auto *FL = dyn_cast<FloatingLiteral>(SubExpr))
+ return this->emitConstBool(FL->getValue().isNonZero(), CE);
if (!this->visit(SubExpr))
return false;
+ return this->emitCastFloatingIntegralBool(getFPOptions(CE), CE);
+ }
+ case CK_FloatingToIntegral: {
+ if (!this->visit(SubExpr))
+ return false;
+ PrimType ToT = classifyPrim(CE);
if (ToT == PT_IntAP)
return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(CE->getType()),
getFPOptions(CE), CE);
@@ -350,7 +351,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(CE->getType()),
getFPOptions(CE), CE);
- return this->emitCastFloatingIntegral(*ToT, getFPOptions(CE), CE);
+ return this->emitCastFloatingIntegral(ToT, getFPOptions(CE), CE);
}
case CK_NullToPointer:
@@ -395,9 +396,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_ArrayToPointerDecay: {
if (!this->visit(SubExpr))
return false;
- if (!this->emitArrayDecay(CE))
- return false;
- return true;
+ return this->emitArrayDecay(CE);
}
case CK_IntegralToPointer: {
@@ -480,47 +479,63 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
return this->emitBuiltinBitCast(CE);
case CK_IntegralToBoolean:
- case CK_FixedPointToBoolean:
+ case CK_FixedPointToBoolean: {
+ // HLSL uses this to cast to one-element vectors.
+ std::optional<PrimType> FromT = classify(SubExpr->getType());
+ if (!FromT)
+ return false;
+
+ if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr))
+ return this->emitConst(IL->getValue(), CE);
+ if (!this->visit(SubExpr))
+ return false;
+ return this->emitCast(*FromT, classifyPrim(CE), CE);
+ }
+
case CK_BooleanToSignedIntegral:
case CK_IntegralCast: {
std::optional<PrimType> FromT = classify(SubExpr->getType());
std::optional<PrimType> ToT = classify(CE->getType());
-
if (!FromT || !ToT)
return false;
- if (!this->visit(SubExpr))
- return false;
+ // Try to emit a casted known constant value directly.
+ if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr)) {
+ if (ToT != PT_IntAP && ToT != PT_IntAPS && FromT != PT_IntAP &&
+ FromT != PT_IntAPS && !CE->getType()->isEnumeralType())
+ return this->emitConst(IL->getValue(), CE);
+ if (!this->emitConst(IL->getValue(), SubExpr))
+ return false;
+ } else {
+ if (!this->visit(SubExpr))
+ return false;
+ }
// Possibly diagnose casts to enum types if the target type does not
// have a fixed size.
if (Ctx.getLangOpts().CPlusPlus && CE->getType()->isEnumeralType()) {
- if (const auto *ET = CE->getType().getCanonicalType()->getAs<EnumType>();
- ET && !ET->getDecl()->isFixed()) {
+ if (const auto *ET = CE->getType().getCanonicalType()->castAs<EnumType>();
+ !ET->getDecl()->isFixed()) {
if (!this->emitCheckEnumValue(*FromT, ET->getDecl(), CE))
return false;
}
}
- auto maybeNegate = [&]() -> bool {
- if (CE->getCastKind() == CK_BooleanToSignedIntegral)
- return this->emitNeg(*ToT, CE);
- return true;
- };
-
- if (ToT == PT_IntAP)
- return this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE) &&
- maybeNegate();
- if (ToT == PT_IntAPS)
- return this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE) &&
- maybeNegate();
-
- if (FromT == ToT)
- return true;
- if (!this->emitCast(*FromT, *ToT, CE))
- return false;
-
- return maybeNegate();
+ if (ToT == PT_IntAP) {
+ if (!this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE))
+ return false;
+ } else if (ToT == PT_IntAPS) {
+ if (!this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE))
+ return false;
+ } else {
+ if (FromT == ToT)
+ return true;
+ if (!this->emitCast(*FromT, *ToT, CE))
+ return false;
+ }
+ if (CE->getCastKind() == CK_BooleanToSignedIntegral)
+ return this->emitNeg(*ToT, CE);
+ return true;
}
case CK_PointerToBoolean:
More information about the cfe-commits
mailing list