Author: Timm Baeder Date: 2025-05-09T09:02:25+02:00 New Revision: 7439d7bdf5aa0069c91693ec590561f234d05c20
URL: https://github.com/llvm/llvm-project/commit/7439d7bdf5aa0069c91693ec590561f234d05c20 DIFF: https://github.com/llvm/llvm-project/commit/7439d7bdf5aa0069c91693ec590561f234d05c20.diff LOG: [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 Added: Modified: clang/lib/AST/ByteCode/Compiler.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index 3cc55c7052d23..51bfa8e548307 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: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits