Skip to content

Commit ae3e30c

Browse files
committed
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.
1 parent c22081c commit ae3e30c

File tree

1 file changed

+60
-47
lines changed

1 file changed

+60
-47
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 60 additions & 47 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,36 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
320320
}
321321

322322
case CK_IntegralToFloating: {
323-
std::optional<PrimType> FromT = classify(SubExpr->getType());
324-
if (!FromT)
325-
return false;
326-
327323
if (!this->visit(SubExpr))
328324
return false;
329-
330325
const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
331-
return this->emitCastIntegralFloating(*FromT, TargetSemantics,
332-
getFPOptions(CE), CE);
326+
return this->emitCastIntegralFloating(
327+
classifyPrim(SubExpr), TargetSemantics, getFPOptions(CE), CE);
333328
}
334329

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

341+
case CK_FloatingToIntegral: {
342+
if (!this->visit(SubExpr))
343+
return false;
344+
PrimType ToT = classifyPrim(CE);
346345
if (ToT == PT_IntAP)
347346
return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(CE->getType()),
348347
getFPOptions(CE), CE);
349348
if (ToT == PT_IntAPS)
350349
return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(CE->getType()),
351350
getFPOptions(CE), CE);
352351

353-
return this->emitCastFloatingIntegral(*ToT, getFPOptions(CE), CE);
352+
return this->emitCastFloatingIntegral(ToT, getFPOptions(CE), CE);
354353
}
355354

356355
case CK_NullToPointer:
@@ -395,9 +394,7 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
395394
case CK_ArrayToPointerDecay: {
396395
if (!this->visit(SubExpr))
397396
return false;
398-
if (!this->emitArrayDecay(CE))
399-
return false;
400-
return true;
397+
return this->emitArrayDecay(CE);
401398
}
402399

403400
case CK_IntegralToPointer: {
@@ -480,47 +477,63 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
480477
return this->emitBuiltinBitCast(CE);
481478

482479
case CK_IntegralToBoolean:
483-
case CK_FixedPointToBoolean:
480+
case CK_FixedPointToBoolean: {
481+
// HLSL uses this to cast to one-element vectors.
482+
std::optional<PrimType> FromT = classify(SubExpr->getType());
483+
if (!FromT)
484+
return false;
485+
486+
if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr))
487+
return this->emitConst(IL->getValue(), CE);
488+
if (!this->visit(SubExpr))
489+
return false;
490+
return this->emitCast(*FromT, classifyPrim(CE), CE);
491+
}
492+
484493
case CK_BooleanToSignedIntegral:
485494
case CK_IntegralCast: {
486495
std::optional<PrimType> FromT = classify(SubExpr->getType());
487496
std::optional<PrimType> ToT = classify(CE->getType());
488-
489497
if (!FromT || !ToT)
490498
return false;
491499

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

495512
// Possibly diagnose casts to enum types if the target type does not
496513
// have a fixed size.
497514
if (Ctx.getLangOpts().CPlusPlus && CE->getType()->isEnumeralType()) {
498-
if (const auto *ET = CE->getType().getCanonicalType()->getAs<EnumType>();
499-
ET && !ET->getDecl()->isFixed()) {
515+
if (const auto *ET = CE->getType().getCanonicalType()->castAs<EnumType>();
516+
!ET->getDecl()->isFixed()) {
500517
if (!this->emitCheckEnumValue(*FromT, ET->getDecl(), CE))
501518
return false;
502519
}
503520
}
504521

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();
522+
if (ToT == PT_IntAP) {
523+
if (!this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE))
524+
return false;
525+
} else if (ToT == PT_IntAPS) {
526+
if (!this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE))
527+
return false;
528+
} else {
529+
if (FromT == ToT)
530+
return true;
531+
if (!this->emitCast(*FromT, *ToT, CE))
532+
return false;
533+
}
534+
if (CE->getCastKind() == CK_BooleanToSignedIntegral)
535+
return this->emitNeg(*ToT, CE);
536+
return true;
524537
}
525538

526539
case CK_PointerToBoolean:

0 commit comments

Comments
 (0)