diff options
author | Timm Baeder <tbaeder@redhat.com> | 2025-05-09 09:02:25 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-09 09:02:25 +0200 |
commit | 7439d7bdf5aa0069c91693ec590561f234d05c20 (patch) | |
tree | 950c6255e4a9a6928b3a5b29ce069acd0e10074d /clang/lib/AST/ByteCode/Compiler.cpp | |
parent | 52924a2d7255cdd280b2b82dad8616e01fe065da (diff) | |
download | llvm-7439d7bdf5aa0069c91693ec590561f234d05c20.zip llvm-7439d7bdf5aa0069c91693ec590561f234d05c20.tar.gz llvm-7439d7bdf5aa0069c91693ec590561f234d05c20.tar.bz2 |
[clang][bytecode] Slightly optimize integral casts of literals (#138879)
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.
This reduces the instruction count by up to 0.13%:
http://llvm-compile-time-tracker.com/compare.php?from=303436c6d16518b35288d63a859506ffcc1681e4&to=648f5202f906d1606390b2d1081e4502dc74acc2&stat=instructions:u
Diffstat (limited to 'clang/lib/AST/ByteCode/Compiler.cpp')
-rw-r--r-- | clang/lib/AST/ByteCode/Compiler.cpp | 107 |
1 files changed, 61 insertions, 46 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 3cc55c7..51bfa8e 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: |