Skip to content

Commit 9b70a28

Browse files
committed
[Transform] Rewrite LowerSwitch using APInt
This rewrite fixes #59316. Previously LowerSwitch uses int64_t, which will crash on case branches using integers with more than 64 bits. Using APInt fixes this problem. This patch also includes a test Reviewed By: RKSimon Differential Revision: https://reviews.llvm.org/D140747
1 parent f9599bb commit 9b70a28

File tree

2 files changed

+40
-10
lines changed

2 files changed

+40
-10
lines changed

llvm/lib/Transforms/Utils/LowerSwitch.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,9 @@ void ProcessSwitchInst(SwitchInst *SI,
370370
const unsigned NumSimpleCases = Clusterify(Cases, SI);
371371
IntegerType *IT = cast<IntegerType>(SI->getCondition()->getType());
372372
const unsigned BitWidth = IT->getBitWidth();
373-
APInt SignedZero(BitWidth, 0);
373+
// Explictly use higher precision to prevent unsigned overflow where
374+
// `UnsignedMax - 0 + 1 == 0`
375+
APInt UnsignedZero(BitWidth + 1, 0);
374376
APInt UnsignedMax = APInt::getMaxValue(BitWidth);
375377
LLVM_DEBUG(dbgs() << "Clusterify finished. Total clusters: " << Cases.size()
376378
<< ". Total non-default cases: " << NumSimpleCases
@@ -431,7 +433,7 @@ void ProcessSwitchInst(SwitchInst *SI,
431433

432434
if (DefaultIsUnreachableFromSwitch) {
433435
DenseMap<BasicBlock *, APInt> Popularity;
434-
APInt MaxPop(SignedZero);
436+
APInt MaxPop(UnsignedZero);
435437
BasicBlock *PopSucc = nullptr;
436438

437439
APInt SignedMax = APInt::getSignedMaxValue(BitWidth);
@@ -457,11 +459,11 @@ void ProcessSwitchInst(SwitchInst *SI,
457459
}
458460

459461
// Count popularity.
460-
APInt N = High - Low + 1;
461-
assert(N.sge(SignedZero) && "Popularity shouldn't be negative.");
462+
assert(High.sge(Low) && "Popularity shouldn't be negative.");
463+
APInt N = High.sext(BitWidth + 1) - Low.sext(BitWidth + 1) + 1;
462464
// Explict insert to make sure the bitwidth of APInts match
463-
APInt &Pop = Popularity.insert({I.BB, APInt(SignedZero)}).first->second;
464-
if ((Pop += N).sgt(MaxPop)) {
465+
APInt &Pop = Popularity.insert({I.BB, APInt(UnsignedZero)}).first->second;
466+
if ((Pop += N).ugt(MaxPop)) {
465467
MaxPop = Pop;
466468
PopSucc = I.BB;
467469
}
@@ -486,8 +488,6 @@ void ProcessSwitchInst(SwitchInst *SI,
486488

487489
// Use the most popular block as the new default, reducing the number of
488490
// cases.
489-
assert(MaxPop.sgt(SignedZero) && PopSucc &&
490-
"Max populartion shouldn't be negative.");
491491
Default = PopSucc;
492492
llvm::erase_if(Cases,
493493
[PopSucc](const CaseRange &R) { return R.BB == PopSucc; });
@@ -498,8 +498,9 @@ void ProcessSwitchInst(SwitchInst *SI,
498498
SI->eraseFromParent();
499499
// As all the cases have been replaced with a single branch, only keep
500500
// one entry in the PHI nodes.
501-
for (APInt I(SignedZero); I.slt(MaxPop - 1); ++I)
502-
PopSucc->removePredecessor(OrigBlock);
501+
if (!MaxPop.isZero())
502+
for (APInt I(UnsignedZero); I.ult(MaxPop - 1); ++I)
503+
PopSucc->removePredecessor(OrigBlock);
503504
return;
504505
}
505506

llvm/test/Transforms/LowerSwitch/pr59316.ll

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,32 @@ BB:
6262
BB1: ; preds = %BB
6363
unreachable
6464
}
65+
66+
define void @f_i1() {
67+
entry:
68+
switch i1 false, label %sw.bb [
69+
i1 false, label %sw.bb12
70+
]
71+
72+
sw.bb: ; preds = %entry
73+
unreachable
74+
75+
sw.bb12: ; preds = %entry
76+
unreachable
77+
}
78+
79+
define void @f_i2(i2 %cond) {
80+
entry:
81+
switch i2 %cond, label %sw.bb [
82+
i2 0, label %sw.bb12
83+
i2 1, label %sw.bb12
84+
i2 2, label %sw.bb12
85+
i2 3, label %sw.bb12
86+
]
87+
88+
sw.bb: ; preds = %entry
89+
unreachable
90+
91+
sw.bb12: ; preds = %entry
92+
unreachable
93+
}

0 commit comments

Comments
 (0)