Skip to content

Commit f7f7574

Browse files
authored
[InstCombine] Canonicalize switch(C-X) to switch(X) (llvm#77051)
This patch canonicalizes `switch(C-X)` to `switch(X)`. Compile-time impact: http://llvm-compile-time-tracker.com/compare.php?from=7954c57124b495fbdc73674d71f2e366e4afe522&to=31a9adff1e633f0f3c423fb8487fc15d17e171f2&stat=instructions:u |stage1-O3|stage1-ReleaseThinLTO|stage1-ReleaseLTO-g|stage1-O0-g|stage2-O3|stage2-O0-g|stage2-clang| |--|--|--|--|--|--|--| |-0.01%|+0.02%|+0.02%|+0.05%|-0.07%|-0.02%|-0.02%|
1 parent 70e6725 commit f7f7574

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3208,6 +3208,18 @@ Instruction *InstCombinerImpl::visitSwitchInst(SwitchInst &SI) {
32083208
return replaceOperand(SI, 0, Op0);
32093209
}
32103210

3211+
ConstantInt *SubLHS;
3212+
if (match(Cond, m_Sub(m_ConstantInt(SubLHS), m_Value(Op0)))) {
3213+
// Change 'switch (1-X) case 1:' into 'switch (X) case 0'.
3214+
for (auto Case : SI.cases()) {
3215+
Constant *NewCase = ConstantExpr::getSub(SubLHS, Case.getCaseValue());
3216+
assert(isa<ConstantInt>(NewCase) &&
3217+
"Result of expression should be constant");
3218+
Case.setValue(cast<ConstantInt>(NewCase));
3219+
}
3220+
return replaceOperand(SI, 0, Op0);
3221+
}
3222+
32113223
KnownBits Known = computeKnownBits(Cond, 0, &SI);
32123224
unsigned LeadingKnownZeros = Known.countMinLeadingZeros();
32133225
unsigned LeadingKnownOnes = Known.countMinLeadingOnes();
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3+
4+
define i1 @test_switch_with_neg(i32 %a) {
5+
; CHECK-LABEL: define i1 @test_switch_with_neg(
6+
; CHECK-SAME: i32 [[A:%.*]]) {
7+
; CHECK-NEXT: entry:
8+
; CHECK-NEXT: switch i32 [[A]], label [[SW_DEFAULT:%.*]] [
9+
; CHECK-NEXT: i32 -37, label [[SW_BB:%.*]]
10+
; CHECK-NEXT: i32 -38, label [[SW_BB]]
11+
; CHECK-NEXT: i32 -39, label [[SW_BB]]
12+
; CHECK-NEXT: ]
13+
; CHECK: sw.bb:
14+
; CHECK-NEXT: ret i1 true
15+
; CHECK: sw.default:
16+
; CHECK-NEXT: ret i1 false
17+
;
18+
entry:
19+
%a.neg = sub i32 0, %a
20+
switch i32 %a.neg, label %sw.default [
21+
i32 37, label %sw.bb
22+
i32 38, label %sw.bb
23+
i32 39, label %sw.bb
24+
]
25+
26+
sw.bb:
27+
ret i1 true
28+
sw.default:
29+
ret i1 false
30+
}
31+
32+
define i1 @test_switch_with_sub(i32 %a) {
33+
; CHECK-LABEL: define i1 @test_switch_with_sub(
34+
; CHECK-SAME: i32 [[A:%.*]]) {
35+
; CHECK-NEXT: entry:
36+
; CHECK-NEXT: switch i32 [[A]], label [[SW_DEFAULT:%.*]] [
37+
; CHECK-NEXT: i32 0, label [[SW_BB:%.*]]
38+
; CHECK-NEXT: i32 -1, label [[SW_BB]]
39+
; CHECK-NEXT: i32 -2, label [[SW_BB]]
40+
; CHECK-NEXT: ]
41+
; CHECK: sw.bb:
42+
; CHECK-NEXT: ret i1 true
43+
; CHECK: sw.default:
44+
; CHECK-NEXT: ret i1 false
45+
;
46+
entry:
47+
%a.neg = sub i32 37, %a
48+
switch i32 %a.neg, label %sw.default [
49+
i32 37, label %sw.bb
50+
i32 38, label %sw.bb
51+
i32 39, label %sw.bb
52+
]
53+
54+
sw.bb:
55+
ret i1 true
56+
sw.default:
57+
ret i1 false
58+
}
59+
60+
; Negative tests
61+
62+
define i1 @test_switch_with_sub_nonconst(i32 %a, i32 %b) {
63+
; CHECK-LABEL: define i1 @test_switch_with_sub_nonconst(
64+
; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]]) {
65+
; CHECK-NEXT: entry:
66+
; CHECK-NEXT: [[A_NEG:%.*]] = sub i32 [[B]], [[A]]
67+
; CHECK-NEXT: switch i32 [[A_NEG]], label [[SW_DEFAULT:%.*]] [
68+
; CHECK-NEXT: i32 37, label [[SW_BB:%.*]]
69+
; CHECK-NEXT: i32 38, label [[SW_BB]]
70+
; CHECK-NEXT: i32 39, label [[SW_BB]]
71+
; CHECK-NEXT: ]
72+
; CHECK: sw.bb:
73+
; CHECK-NEXT: ret i1 true
74+
; CHECK: sw.default:
75+
; CHECK-NEXT: ret i1 false
76+
;
77+
entry:
78+
%a.neg = sub i32 %b, %a
79+
switch i32 %a.neg, label %sw.default [
80+
i32 37, label %sw.bb
81+
i32 38, label %sw.bb
82+
i32 39, label %sw.bb
83+
]
84+
85+
sw.bb:
86+
ret i1 true
87+
sw.default:
88+
ret i1 false
89+
}

0 commit comments

Comments
 (0)