Skip to content

Commit cef9fbd

Browse files
committed
[SimplifyCFG] Don't use a mask when converting a switch with an unreachable default branch to a lookup table
This make it possible to convert large switches (whose lookup table size would exceed the target register bit width) with holes and an unreachable default case into lookup tables.
1 parent e15d3ed commit cef9fbd

File tree

4 files changed

+42
-230
lines changed

4 files changed

+42
-230
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6743,8 +6743,15 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
67436743
TableSize =
67446744
(MaxCaseVal->getValue() - MinCaseVal->getValue()).getLimitedValue() + 1;
67456745

6746+
// If the default destination is unreachable, or if the lookup table covers
6747+
// all values of the conditional variable, branch directly to the lookup table
6748+
// BB. Otherwise, check that the condition is within the case range.
6749+
bool DefaultIsReachable =
6750+
!isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
6751+
67466752
bool TableHasHoles = (NumResults < TableSize);
6747-
bool NeedMask = (TableHasHoles && !HasDefaultResults);
6753+
bool HolesHaveUndefinedResults = (TableHasHoles && !HasDefaultResults);
6754+
bool NeedMask = (HolesHaveUndefinedResults && DefaultIsReachable);
67486755
if (NeedMask) {
67496756
// As an extra penalty for the validity test we require more cases.
67506757
if (SI->getNumCases() < 4) // FIXME: Find best threshold value (benchmark).
@@ -6766,12 +6773,6 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
67666773
"It is impossible for a switch to have more entries than the max "
67676774
"representable value of its input integer type's size.");
67686775

6769-
// If the default destination is unreachable, or if the lookup table covers
6770-
// all values of the conditional variable, branch directly to the lookup table
6771-
// BB. Otherwise, check that the condition is within the case range.
6772-
bool DefaultIsReachable =
6773-
!isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
6774-
67756776
// Create the BB that does the lookups.
67766777
Module &Mod = *CommonDest->getParent()->getParent();
67776778
BasicBlock *LookupBB = BasicBlock::Create(
@@ -6895,8 +6896,9 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
68956896
for (PHINode *PHI : PHIs) {
68966897
const ResultListTy &ResultList = ResultLists[PHI];
68976898

6898-
// If using a bitmask, use any value to fill the lookup table holes.
6899-
Constant *DV = NeedMask ? ResultLists[PHI][0].second : DefaultResults[PHI];
6899+
// Use any value to fill the lookup table holes.
6900+
Constant *DV = HolesHaveUndefinedResults ? ResultLists[PHI][0].second
6901+
: DefaultResults[PHI];
69006902
StringRef FuncName = Fn->getName();
69016903
SwitchLookupTable Table(Mod, TableSize, TableIndexOffset, ResultList, DV,
69026904
DL, FuncName);

llvm/test/Transforms/SimplifyCFG/RISCV/switch-of-powers-of-two.ll

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ define i32 @switch_of_powers(i32 %x) {
3434
; RV64ZBB-LABEL: @switch_of_powers(
3535
; RV64ZBB-NEXT: entry:
3636
; RV64ZBB-NEXT: [[TMP0:%.*]] = call i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)
37-
; RV64ZBB-NEXT: [[SWITCH_MASKINDEX:%.*]] = trunc i32 [[TMP0]] to i8
38-
; RV64ZBB-NEXT: [[SWITCH_SHIFTED:%.*]] = lshr i8 121, [[SWITCH_MASKINDEX]]
39-
; RV64ZBB-NEXT: [[SWITCH_LOBIT:%.*]] = trunc i8 [[SWITCH_SHIFTED]] to i1
40-
; RV64ZBB-NEXT: call void @llvm.assume(i1 [[SWITCH_LOBIT]])
4137
; RV64ZBB-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [7 x i32], ptr @switch.table.switch_of_powers, i32 0, i32 [[TMP0]]
4238
; RV64ZBB-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
4339
; RV64ZBB-NEXT: ret i32 [[SWITCH_LOAD]]

llvm/test/Transforms/SimplifyCFG/X86/switch_to_lookup_table.ll

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,20 +1732,11 @@ define i32 @signed_overflow2(i8 %n) {
17321732
; CHECK-LABEL: @signed_overflow2(
17331733
; CHECK-NEXT: start:
17341734
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i2
1735-
; CHECK-NEXT: switch i2 [[TRUNC]], label [[BB1:%.*]] [
1736-
; CHECK-NEXT: i2 1, label [[BB6:%.*]]
1737-
; CHECK-NEXT: i2 -2, label [[BB4:%.*]]
1738-
; CHECK-NEXT: i2 -1, label [[BB5:%.*]]
1739-
; CHECK-NEXT: ]
1740-
; CHECK: bb1:
1741-
; CHECK-NEXT: unreachable
1742-
; CHECK: bb4:
1743-
; CHECK-NEXT: br label [[BB6]]
1744-
; CHECK: bb5:
1745-
; CHECK-NEXT: br label [[BB6]]
1746-
; CHECK: bb6:
1747-
; CHECK-NEXT: [[DOTSROA_0_0:%.*]] = phi i32 [ 4444, [[BB5]] ], [ 3333, [[BB4]] ], [ 2222, [[START:%.*]] ]
1748-
; CHECK-NEXT: ret i32 [[DOTSROA_0_0]]
1735+
; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], -2
1736+
; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3
1737+
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.signed_overflow2, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]]
1738+
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
1739+
; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
17491740
;
17501741
start:
17511742
%trunc = trunc i8 %n to i2

0 commit comments

Comments
 (0)