[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 01:18:01 PDT 2025
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/138879
>From d20a16354c6f61ecb62ce68239eb3f94adc6f6e1 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 | 111 +++++++++++++++-------------
1 file changed, 60 insertions(+), 51 deletions(-)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index ae6574cf99159..3d621d194e61d 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,26 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
}
case CK_IntegralToFloating: {
- std::optional<PrimType> FromT = classify(SubExpr->getType());
- if (!FromT)
- 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: {
+ assert(classifyPrim(CE) == PT_Bool);
+ 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 +347,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 +392,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 +475,61 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
return this->emitBuiltinBitCast(CE);
case CK_IntegralToBoolean:
- case CK_FixedPointToBoolean:
- case CK_BooleanToSignedIntegral:
- case CK_IntegralCast: {
- std::optional<PrimType> FromT = classify(SubExpr->getType());
- std::optional<PrimType> ToT = classify(CE->getType());
+ case CK_FixedPointToBoolean: {
+ assert(classifyPrim(CE) == PT_Bool);
- if (!FromT || !ToT)
- return false;
+ if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr))
+ return this->emitConstBool(!IL->getValue().isZero(), CE);
if (!this->visit(SubExpr))
return false;
+ PrimType FromT = classifyPrim(SubExpr->getType());
+ if (FromT == PT_Bool)
+ return true;
+ return this->emitCast(FromT, PT_Bool, CE);
+ }
+
+ case CK_BooleanToSignedIntegral:
+ case CK_IntegralCast: {
+ PrimType FromT = classifyPrim(SubExpr->getType());
+ PrimType ToT = classifyPrim(CE->getType());
+
+ if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr)) {
+ if (ToT != PT_IntAP && ToT != 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 (!this->emitCheckEnumValue(*FromT, ET->getDecl(), CE))
+ 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