Skip to content

Commit cbf2a2d

Browse files
committed
[SimplifyCFG] Don't use a mask when converting a switch with an unreachable default branch to a lookup table
This makes 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 faabae0 commit cbf2a2d

File tree

4 files changed

+32
-81
lines changed

4 files changed

+32
-81
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6743,8 +6743,25 @@ 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 = !SI->defaultDestUndefined();
6750+
67466751
bool TableHasHoles = (NumResults < TableSize);
6747-
bool NeedMask = (TableHasHoles && !HasDefaultResults);
6752+
6753+
// If the table has holes but the default destination doesn't produce any
6754+
// constant results, the lookup table entries corresponding to the holes will
6755+
// contain undefined values.
6756+
bool AllHolesAreUndefined = TableHasHoles && !HasDefaultResults;
6757+
6758+
// If the default destination doesn't produce a constant result but is still
6759+
// reachable, and the lookup table has holes, we need to use a mask to
6760+
// determine if the current index should load from the lookup table or jump
6761+
// to the default case.
6762+
// The mask is unnecessary if the table has holes but the default destination
6763+
// is unreachable, as in that case the holes must also be unreachable.
6764+
bool NeedMask = AllHolesAreUndefined && DefaultIsReachable;
67486765
if (NeedMask) {
67496766
// As an extra penalty for the validity test we require more cases.
67506767
if (SI->getNumCases() < 4) // FIXME: Find best threshold value (benchmark).
@@ -6766,12 +6783,6 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
67666783
"It is impossible for a switch to have more entries than the max "
67676784
"representable value of its input integer type's size.");
67686785

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-
67756786
// Create the BB that does the lookups.
67766787
Module &Mod = *CommonDest->getParent()->getParent();
67776788
BasicBlock *LookupBB = BasicBlock::Create(
@@ -6895,8 +6906,9 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
68956906
for (PHINode *PHI : PHIs) {
68966907
const ResultListTy &ResultList = ResultLists[PHI];
68976908

6898-
// If using a bitmask, use any value to fill the lookup table holes.
6899-
Constant *DV = NeedMask ? ResultLists[PHI][0].second : DefaultResults[PHI];
6909+
// Use any value to fill the lookup table holes.
6910+
Constant *DV =
6911+
AllHolesAreUndefined ? ResultLists[PHI][0].second : DefaultResults[PHI];
69006912
StringRef FuncName = Fn->getName();
69016913
SwitchLookupTable Table(Mod, TableSize, TableIndexOffset, ResultList, DV,
69026914
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: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ target triple = "x86_64-unknown-linux-gnu"
3838
; CHECK: @switch.table.threecases = private unnamed_addr constant [3 x i32] [i32 10, i32 7, i32 5], align 4
3939
; CHECK: @switch.table.covered_switch_with_bit_tests = private unnamed_addr constant [8 x i32] [i32 2, i32 2, i32 2, i32 2, i32 2, i32 2, i32 1, i32 1], align 4
4040
; CHECK: @switch.table.signed_overflow1 = private unnamed_addr constant [4 x i32] [i32 3333, i32 4444, i32 1111, i32 2222], align 4
41+
; CHECK: @switch.table.signed_overflow2 = private unnamed_addr constant [4 x i32] [i32 3333, i32 4444, i32 2222, i32 2222], align 4
4142
;.
4243
define i32 @f(i32 %c) {
4344
; CHECK-LABEL: @f(
@@ -1738,20 +1739,11 @@ define i32 @signed_overflow2(i8 %n) {
17381739
; CHECK-LABEL: @signed_overflow2(
17391740
; CHECK-NEXT: start:
17401741
; CHECK-NEXT: [[TRUNC:%.*]] = trunc i8 [[N:%.*]] to i2
1741-
; CHECK-NEXT: switch i2 [[TRUNC]], label [[BB1:%.*]] [
1742-
; CHECK-NEXT: i2 1, label [[BB6:%.*]]
1743-
; CHECK-NEXT: i2 -2, label [[BB4:%.*]]
1744-
; CHECK-NEXT: i2 -1, label [[BB5:%.*]]
1745-
; CHECK-NEXT: ]
1746-
; CHECK: bb1:
1747-
; CHECK-NEXT: unreachable
1748-
; CHECK: bb4:
1749-
; CHECK-NEXT: br label [[BB6]]
1750-
; CHECK: bb5:
1751-
; CHECK-NEXT: br label [[BB6]]
1752-
; CHECK: bb6:
1753-
; CHECK-NEXT: [[DOTSROA_0_0:%.*]] = phi i32 [ 4444, [[BB5]] ], [ 3333, [[BB4]] ], [ 2222, [[START:%.*]] ]
1754-
; CHECK-NEXT: ret i32 [[DOTSROA_0_0]]
1742+
; CHECK-NEXT: [[SWITCH_TABLEIDX:%.*]] = sub i2 [[TRUNC]], -2
1743+
; CHECK-NEXT: [[SWITCH_TABLEIDX_ZEXT:%.*]] = zext i2 [[SWITCH_TABLEIDX]] to i3
1744+
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [4 x i32], ptr @switch.table.signed_overflow2, i32 0, i3 [[SWITCH_TABLEIDX_ZEXT]]
1745+
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
1746+
; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
17551747
;
17561748
start:
17571749
%trunc = trunc i8 %n to i2

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

Lines changed: 5 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt < %s -passes=simplifycfg -switch-to-lookup=true -keep-loops=false -S | FileCheck %s
3-
; RUN: opt < %s -passes='simplifycfg<no-keep-loops;switch-to-lookup>' -S | FileCheck %s
2+
; RUN: opt < %s -passes=simplifycfg -switch-to-lookup=true -S | FileCheck %s
43
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
54
target triple = "i386-pc-linux-gnu"
65

@@ -198,10 +197,7 @@ return:
198197
define i32 @unreachable_default_holes_0to31(i32 %x, i32 %y) {
199198
; CHECK-LABEL: @unreachable_default_holes_0to31(
200199
; CHECK-NEXT: entry:
201-
; CHECK-NEXT: [[SWITCH_SHIFTED:%.*]] = lshr i32 -277094665, [[X:%.*]]
202-
; CHECK-NEXT: [[SWITCH_LOBIT:%.*]] = trunc i32 [[SWITCH_SHIFTED]] to i1
203-
; CHECK-NEXT: call void @llvm.assume(i1 [[SWITCH_LOBIT]])
204-
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i32], ptr @switch.table.unreachable_default_holes_0to31, i32 0, i32 [[X]]
200+
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [32 x i32], ptr @switch.table.unreachable_default_holes_0to31, i32 0, i32 [[X:%.*]]
205201
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
206202
; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
207203
;
@@ -485,54 +481,9 @@ return:
485481
define i32 @unreachable_default_holes_0to32(i32 %x, i32 %y) {
486482
; CHECK-LABEL: @unreachable_default_holes_0to32(
487483
; CHECK-NEXT: entry:
488-
; CHECK-NEXT: switch i32 [[X:%.*]], label [[SW_DEFAULT:%.*]] [
489-
; CHECK-NEXT: i32 0, label [[RETURN:%.*]]
490-
; CHECK-NEXT: i32 1, label [[BB7:%.*]]
491-
; CHECK-NEXT: i32 2, label [[BB6:%.*]]
492-
; CHECK-NEXT: i32 4, label [[BB4:%.*]]
493-
; CHECK-NEXT: i32 5, label [[BB3:%.*]]
494-
; CHECK-NEXT: i32 6, label [[BB2:%.*]]
495-
; CHECK-NEXT: i32 7, label [[BB1:%.*]]
496-
; CHECK-NEXT: i32 9, label [[BB7]]
497-
; CHECK-NEXT: i32 10, label [[BB6]]
498-
; CHECK-NEXT: i32 11, label [[BB5:%.*]]
499-
; CHECK-NEXT: i32 12, label [[BB4]]
500-
; CHECK-NEXT: i32 14, label [[BB2]]
501-
; CHECK-NEXT: i32 15, label [[BB1]]
502-
; CHECK-NEXT: i32 16, label [[RETURN]]
503-
; CHECK-NEXT: i32 17, label [[BB7]]
504-
; CHECK-NEXT: i32 19, label [[BB5]]
505-
; CHECK-NEXT: i32 20, label [[BB4]]
506-
; CHECK-NEXT: i32 21, label [[BB3]]
507-
; CHECK-NEXT: i32 22, label [[BB2]]
508-
; CHECK-NEXT: i32 24, label [[RETURN]]
509-
; CHECK-NEXT: i32 25, label [[BB7]]
510-
; CHECK-NEXT: i32 26, label [[BB6]]
511-
; CHECK-NEXT: i32 27, label [[BB5]]
512-
; CHECK-NEXT: i32 29, label [[BB3]]
513-
; CHECK-NEXT: i32 30, label [[BB2]]
514-
; CHECK-NEXT: i32 31, label [[BB1]]
515-
; CHECK-NEXT: i32 32, label [[RETURN]]
516-
; CHECK-NEXT: ]
517-
; CHECK: sw.default:
518-
; CHECK-NEXT: unreachable
519-
; CHECK: bb1:
520-
; CHECK-NEXT: br label [[RETURN]]
521-
; CHECK: bb2:
522-
; CHECK-NEXT: br label [[RETURN]]
523-
; CHECK: bb3:
524-
; CHECK-NEXT: br label [[RETURN]]
525-
; CHECK: bb4:
526-
; CHECK-NEXT: br label [[RETURN]]
527-
; CHECK: bb5:
528-
; CHECK-NEXT: br label [[RETURN]]
529-
; CHECK: bb6:
530-
; CHECK-NEXT: br label [[RETURN]]
531-
; CHECK: bb7:
532-
; CHECK-NEXT: br label [[RETURN]]
533-
; CHECK: return:
534-
; CHECK-NEXT: [[RES:%.*]] = phi i32 [ 1, [[BB1]] ], [ 2, [[BB2]] ], [ 3, [[BB3]] ], [ 4, [[BB4]] ], [ 5, [[BB5]] ], [ 6, [[BB6]] ], [ 7, [[BB7]] ], [ 0, [[ENTRY:%.*]] ], [ 0, [[ENTRY]] ], [ 0, [[ENTRY]] ], [ 0, [[ENTRY]] ]
535-
; CHECK-NEXT: ret i32 [[RES]]
484+
; CHECK-NEXT: [[SWITCH_GEP:%.*]] = getelementptr inbounds [33 x i32], ptr @switch.table.unreachable_default_holes_0to32, i32 0, i32 [[X:%.*]]
485+
; CHECK-NEXT: [[SWITCH_LOAD:%.*]] = load i32, ptr [[SWITCH_GEP]], align 4
486+
; CHECK-NEXT: ret i32 [[SWITCH_LOAD]]
536487
;
537488
entry:
538489
switch i32 %x, label %sw.default [

0 commit comments

Comments
 (0)