Skip to content

Commit 5e07481

Browse files
committed
[SimplifyCFG] Delete the unnecessary range check for small mask operation
When the small mask value little than 64, we can eliminate the checking for upper limit of the range by enlarge the lookup table size to the maximum index value. (Then the final table size grows to the next pow2 value) ``` bool f(unsigned x) { switch (x % 8) { case 0: return 1; case 1: return 0; case 2: return 0; case 3: return 1; case 4: return 1; case 5: return 0; case 6: return 1; // This would remove the range check: case 7: return 0; } return 0; } ``` Use WouldFitInRegister instead of fitsInLegalInteger to support more result type beside bool. Fixes #65120 Reviewed By: zmodem, nikic, RKSimon
1 parent 925f462 commit 5e07481

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6598,9 +6598,8 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
65986598
// If the default destination is unreachable, or if the lookup table covers
65996599
// all values of the conditional variable, branch directly to the lookup table
66006600
// BB. Otherwise, check that the condition is within the case range.
6601-
const bool DefaultIsReachable =
6601+
bool DefaultIsReachable =
66026602
!isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg());
6603-
const bool GeneratingCoveredLookupTable = (MaxTableSize == TableSize);
66046603

66056604
// Create the BB that does the lookups.
66066605
Module &Mod = *CommonDest->getParent()->getParent();
@@ -6631,6 +6630,25 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
66316630

66326631
BranchInst *RangeCheckBranch = nullptr;
66336632

6633+
// Grow the table to cover all possible index values to avoid the range check.
6634+
if (UseSwitchConditionAsTableIndex) {
6635+
ConstantRange CR = computeConstantRange(TableIndex, /* ForSigned */ false);
6636+
// Grow the table shouldn't have any size impact by checking
6637+
// WouldFitInRegister.
6638+
// TODO: Consider growing the table also when it doesn't fit in a register
6639+
// if no optsize is specified.
6640+
if (all_of(ResultTypes, [&](const auto &KV) {
6641+
return SwitchLookupTable::WouldFitInRegister(
6642+
DL, CR.getUpper().getLimitedValue(), KV.second /* ResultType */);
6643+
})) {
6644+
// The default branch is unreachable when we enlarge the lookup table.
6645+
// Adjust DefaultIsReachable to reuse code path.
6646+
TableSize = CR.getUpper().getZExtValue();
6647+
DefaultIsReachable = false;
6648+
}
6649+
}
6650+
6651+
const bool GeneratingCoveredLookupTable = (MaxTableSize == TableSize);
66346652
if (!DefaultIsReachable || GeneratingCoveredLookupTable) {
66356653
Builder.CreateBr(LookupBB);
66366654
if (DTU)

llvm/test/Transforms/SimplifyCFG/switch_mask.ll

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ define i1 @switch_lookup_with_small_i1(i64 %x) {
88
; CHECK-LABEL: @switch_lookup_with_small_i1(
99
; CHECK-NEXT: entry:
1010
; CHECK-NEXT: [[AND:%.*]] = and i64 [[X:%.*]], 15
11-
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[AND]], 11
12-
; CHECK-NEXT: [[SWITCH_CAST:%.*]] = trunc i64 [[AND]] to i11
13-
; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i11 [[SWITCH_CAST]], 1
14-
; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i11 -1018, [[SWITCH_SHIFTAMT]]
15-
; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i11 [[SWITCH_DOWNSHIFT]] to i1
16-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i1 [[SWITCH_MASKED]], i1 false
17-
; CHECK-NEXT: ret i1 [[TMP1]]
11+
; CHECK-NEXT: [[SWITCH_CAST:%.*]] = trunc i64 [[AND]] to i16
12+
; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i16 [[SWITCH_CAST]], 1
13+
; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i16 1030, [[SWITCH_SHIFTAMT]]
14+
; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i16 [[SWITCH_DOWNSHIFT]] to i1
15+
; CHECK-NEXT: ret i1 [[SWITCH_MASKED]]
1816
;
1917
entry:
2018
%and = and i64 %x, 15
@@ -37,13 +35,11 @@ define i8 @switch_lookup_with_small_i8(i64 %x) {
3735
; CHECK-LABEL: @switch_lookup_with_small_i8(
3836
; CHECK-NEXT: entry:
3937
; CHECK-NEXT: [[REM:%.*]] = urem i64 [[X:%.*]], 5
40-
; CHECK-NEXT: [[TMP0:%.*]] = icmp ult i64 [[REM]], 3
41-
; CHECK-NEXT: [[SWITCH_CAST:%.*]] = trunc i64 [[REM]] to i24
42-
; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i24 [[SWITCH_CAST]], 8
43-
; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i24 460303, [[SWITCH_SHIFTAMT]]
44-
; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i24 [[SWITCH_DOWNSHIFT]] to i8
45-
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[TMP0]], i8 [[SWITCH_MASKED]], i8 0
46-
; CHECK-NEXT: ret i8 [[TMP1]]
38+
; CHECK-NEXT: [[SWITCH_CAST:%.*]] = trunc i64 [[REM]] to i40
39+
; CHECK-NEXT: [[SWITCH_SHIFTAMT:%.*]] = mul nuw nsw i40 [[SWITCH_CAST]], 8
40+
; CHECK-NEXT: [[SWITCH_DOWNSHIFT:%.*]] = lshr i40 460303, [[SWITCH_SHIFTAMT]]
41+
; CHECK-NEXT: [[SWITCH_MASKED:%.*]] = trunc i40 [[SWITCH_DOWNSHIFT]] to i8
42+
; CHECK-NEXT: ret i8 [[SWITCH_MASKED]]
4743
;
4844
entry:
4945
%rem = urem i64 %x, 5

0 commit comments

Comments
 (0)