Skip to content

Commit 7439d7b

Browse files
authored
[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
1 parent 52924a2 commit 7439d7b

File tree

1 file changed

+61
-46
lines changed

1 file changed

+61
-46
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 61 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
238238
case CK_DerivedToBaseMemberPointer: {
239239
assert(classifyPrim(CE->getType()) == PT_MemberPtr);
240240
assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr);
241-
const auto *FromMP = SubExpr->getType()->getAs<MemberPointerType>();
242-
const auto *ToMP = CE->getType()->getAs<MemberPointerType>();
241+
const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();
242+
const auto *ToMP = CE->getType()->castAs<MemberPointerType>();
243243

244244
unsigned DerivedOffset =
245245
Ctx.collectBaseOffset(ToMP->getMostRecentCXXRecordDecl(),
@@ -254,8 +254,8 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
254254
case CK_BaseToDerivedMemberPointer: {
255255
assert(classifyPrim(CE) == PT_MemberPtr);
256256
assert(classifyPrim(SubExpr) == PT_MemberPtr);
257-
const auto *FromMP = SubExpr->getType()->getAs<MemberPointerType>();
258-
const auto *ToMP = CE->getType()->getAs<MemberPointerType>();
257+
const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();
258+
const auto *ToMP = CE->getType()->castAs<MemberPointerType>();
259259

260260
unsigned DerivedOffset =
261261
Ctx.collectBaseOffset(FromMP->getMostRecentCXXRecordDecl(),
@@ -320,37 +320,38 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
320320
}
321321

322322
case CK_IntegralToFloating: {
323-
std::optional<PrimType> FromT = classify(SubExpr->getType());
324-
if (!FromT)
323+
if (!CE->getType()->isRealFloatingType())
325324
return false;
326-
327325
if (!this->visit(SubExpr))
328326
return false;
329-
330327
const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
331-
return this->emitCastIntegralFloating(*FromT, TargetSemantics,
332-
getFPOptions(CE), CE);
328+
return this->emitCastIntegralFloating(
329+
classifyPrim(SubExpr), TargetSemantics, getFPOptions(CE), CE);
333330
}
334331

335-
case CK_FloatingToBoolean:
336-
case CK_FloatingToIntegral: {
337-
338-
std::optional<PrimType> ToT = classify(CE->getType());
339-
340-
if (!ToT)
332+
case CK_FloatingToBoolean: {
333+
if (!SubExpr->getType()->isRealFloatingType() ||
334+
!CE->getType()->isBooleanType())
341335
return false;
342-
336+
if (const auto *FL = dyn_cast<FloatingLiteral>(SubExpr))
337+
return this->emitConstBool(FL->getValue().isNonZero(), CE);
343338
if (!this->visit(SubExpr))
344339
return false;
340+
return this->emitCastFloatingIntegralBool(getFPOptions(CE), CE);
341+
}
345342

343+
case CK_FloatingToIntegral: {
344+
if (!this->visit(SubExpr))
345+
return false;
346+
PrimType ToT = classifyPrim(CE);
346347
if (ToT == PT_IntAP)
347348
return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(CE->getType()),
348349
getFPOptions(CE), CE);
349350
if (ToT == PT_IntAPS)
350351
return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(CE->getType()),
351352
getFPOptions(CE), CE);
352353

353-
return this->emitCastFloatingIntegral(*ToT, getFPOptions(CE), CE);
354+
return this->emitCastFloatingIntegral(ToT, getFPOptions(CE), CE);
354355
}
355356

356357
case CK_NullToPointer:
@@ -395,9 +396,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
395396
case CK_ArrayToPointerDecay: {
396397
if (!this->visit(SubExpr))
397398
return false;
398-
if (!this->emitArrayDecay(CE))
399-
return false;
400-
return true;
399+
return this->emitArrayDecay(CE);
401400
}
402401

403402
case CK_IntegralToPointer: {
@@ -480,47 +479,63 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
480479
return this->emitBuiltinBitCast(CE);
481480

482481
case CK_IntegralToBoolean:
483-
case CK_FixedPointToBoolean:
482+
case CK_FixedPointToBoolean: {
483+
// HLSL uses this to cast to one-element vectors.
484+
std::optional<PrimType> FromT = classify(SubExpr->getType());
485+
if (!FromT)
486+
return false;
487+
488+
if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr))
489+
return this->emitConst(IL->getValue(), CE);
490+
if (!this->visit(SubExpr))
491+
return false;
492+
return this->emitCast(*FromT, classifyPrim(CE), CE);
493+
}
494+
484495
case CK_BooleanToSignedIntegral:
485496
case CK_IntegralCast: {
486497
std::optional<PrimType> FromT = classify(SubExpr->getType());
487498
std::optional<PrimType> ToT = classify(CE->getType());
488-
489499
if (!FromT || !ToT)
490500
return false;
491501

492-
if (!this->visit(SubExpr))
493-
return false;
502+
// Try to emit a casted known constant value directly.
503+
if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr)) {
504+
if (ToT != PT_IntAP && ToT != PT_IntAPS && FromT != PT_IntAP &&
505+
FromT != PT_IntAPS && !CE->getType()->isEnumeralType())
506+
return this->emitConst(IL->getValue(), CE);
507+
if (!this->emitConst(IL->getValue(), SubExpr))
508+
return false;
509+
} else {
510+
if (!this->visit(SubExpr))
511+
return false;
512+
}
494513

495514
// Possibly diagnose casts to enum types if the target type does not
496515
// have a fixed size.
497516
if (Ctx.getLangOpts().CPlusPlus && CE->getType()->isEnumeralType()) {
498-
if (const auto *ET = CE->getType().getCanonicalType()->getAs<EnumType>();
499-
ET && !ET->getDecl()->isFixed()) {
517+
if (const auto *ET = CE->getType().getCanonicalType()->castAs<EnumType>();
518+
!ET->getDecl()->isFixed()) {
500519
if (!this->emitCheckEnumValue(*FromT, ET->getDecl(), CE))
501520
return false;
502521
}
503522
}
504523

505-
auto maybeNegate = [&]() -> bool {
506-
if (CE->getCastKind() == CK_BooleanToSignedIntegral)
507-
return this->emitNeg(*ToT, CE);
508-
return true;
509-
};
510-
511-
if (ToT == PT_IntAP)
512-
return this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE) &&
513-
maybeNegate();
514-
if (ToT == PT_IntAPS)
515-
return this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE) &&
516-
maybeNegate();
517-
518-
if (FromT == ToT)
519-
return true;
520-
if (!this->emitCast(*FromT, *ToT, CE))
521-
return false;
522-
523-
return maybeNegate();
524+
if (ToT == PT_IntAP) {
525+
if (!this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE))
526+
return false;
527+
} else if (ToT == PT_IntAPS) {
528+
if (!this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE))
529+
return false;
530+
} else {
531+
if (FromT == ToT)
532+
return true;
533+
if (!this->emitCast(*FromT, *ToT, CE))
534+
return false;
535+
}
536+
if (CE->getCastKind() == CK_BooleanToSignedIntegral)
537+
return this->emitNeg(*ToT, CE);
538+
return true;
524539
}
525540

526541
case CK_PointerToBoolean:

0 commit comments

Comments
 (0)