Skip to content

Commit f782c5e

Browse files
committed
[InstCombine] Simplify switch with selects
1 parent 4e5e922 commit f782c5e

File tree

2 files changed

+45
-9
lines changed

2 files changed

+45
-9
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3334,6 +3334,37 @@ Instruction *InstCombinerImpl::visitBranchInst(BranchInst &BI) {
33343334
return nullptr;
33353335
}
33363336

3337+
// Replaces (switch (select cond, X, C)/(select cond, C, X)) with (switch X) if
3338+
// we can prove that both (switch C) and (switch X) go to the default when cond
3339+
// is false/true.
3340+
static Value *simplifySwitchOnSelectUsingRanges(SwitchInst &SI,
3341+
SelectInst *Select,
3342+
unsigned CstOpIdx) {
3343+
auto *C = dyn_cast<ConstantInt>(Select->getOperand(CstOpIdx));
3344+
if (!C)
3345+
return nullptr;
3346+
3347+
BasicBlock *CstBB = SI.findCaseValue(C)->getCaseSuccessor();
3348+
if (CstBB != SI.getDefaultDest())
3349+
return nullptr;
3350+
Value *X = Select->getOperand(3 - CstOpIdx);
3351+
ICmpInst::Predicate Pred;
3352+
const APInt *RHSC;
3353+
if (!match(Select->getCondition(),
3354+
m_ICmp(Pred, m_Specific(X), m_APInt(RHSC))))
3355+
return nullptr;
3356+
if (CstOpIdx == 1)
3357+
Pred = ICmpInst::getInversePredicate(Pred);
3358+
3359+
// See whether we can replace the select with X
3360+
ConstantRange CR = ConstantRange::makeExactICmpRegion(Pred, *RHSC);
3361+
for (auto Case : SI.cases())
3362+
if (!CR.contains(Case.getCaseValue()->getValue()))
3363+
return nullptr;
3364+
3365+
return X;
3366+
}
3367+
33373368
Instruction *InstCombinerImpl::visitSwitchInst(SwitchInst &SI) {
33383369
Value *Cond = SI.getCondition();
33393370
Value *Op0;
@@ -3407,6 +3438,16 @@ Instruction *InstCombinerImpl::visitSwitchInst(SwitchInst &SI) {
34073438
}
34083439
}
34093440

3441+
// Fold switch(select cond, X, Y) into switch(X/Y) if possible
3442+
if (auto *Select = dyn_cast<SelectInst>(Cond)) {
3443+
if (Value *V =
3444+
simplifySwitchOnSelectUsingRanges(SI, Select, /*CstOpIdx=*/1))
3445+
return replaceOperand(SI, 0, V);
3446+
if (Value *V =
3447+
simplifySwitchOnSelectUsingRanges(SI, Select, /*CstOpIdx=*/2))
3448+
return replaceOperand(SI, 0, V);
3449+
}
3450+
34103451
KnownBits Known = computeKnownBits(Cond, 0, &SI);
34113452
unsigned LeadingKnownZeros = Known.countMinLeadingZeros();
34123453
unsigned LeadingKnownOnes = Known.countMinLeadingOnes();

llvm/test/Transforms/InstCombine/switch-select.ll

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,9 @@
44
define void @test_ult_rhsc(i8 %x) {
55
; CHECK-LABEL: define void @test_ult_rhsc(
66
; CHECK-SAME: i8 [[X:%.*]]) {
7-
; CHECK-NEXT: [[VAL:%.*]] = add nsw i8 [[X]], -2
8-
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[VAL]], 11
9-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 [[VAL]], i8 6
10-
; CHECK-NEXT: switch i8 [[COND]], label [[BB1:%.*]] [
11-
; CHECK-NEXT: i8 0, label [[BB2:%.*]]
12-
; CHECK-NEXT: i8 10, label [[BB3:%.*]]
7+
; CHECK-NEXT: switch i8 [[X]], label [[BB1:%.*]] [
8+
; CHECK-NEXT: i8 2, label [[BB2:%.*]]
9+
; CHECK-NEXT: i8 12, label [[BB3:%.*]]
1310
; CHECK-NEXT: ]
1411
; CHECK: bb1:
1512
; CHECK-NEXT: call void @func1()
@@ -43,9 +40,7 @@ bb3:
4340
define void @test_eq_lhsc(i8 %x) {
4441
; CHECK-LABEL: define void @test_eq_lhsc(
4542
; CHECK-SAME: i8 [[X:%.*]]) {
46-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X]], 4
47-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i8 6, i8 [[X]]
48-
; CHECK-NEXT: switch i8 [[COND]], label [[BB1:%.*]] [
43+
; CHECK-NEXT: switch i8 [[X]], label [[BB1:%.*]] [
4944
; CHECK-NEXT: i8 0, label [[BB2:%.*]]
5045
; CHECK-NEXT: i8 10, label [[BB3:%.*]]
5146
; CHECK-NEXT: ]

0 commit comments

Comments
 (0)