Skip to content

Commit 9bad7de

Browse files
committed
[SimplifyCFG] Handle two equal cases in switch to select
When converting a switch with two cases and a default into a select, also handle the denegerate case where two cases have the same value. Generate this case directly as %or = or i1 %cmp1, %cmp2 %res = select i1 %or, i32 %val, i32 %default rather than %sel1 = select i1 %cmp1, i32 %val, i32 %default %res = select i1 %cmp2, i32 %val, i32 %sel1 as InstCombine is going to canonicalize to the former anyway.
1 parent 7ca168d commit 9bad7de

File tree

3 files changed

+23
-32
lines changed

3 files changed

+23
-32
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5287,11 +5287,9 @@ InitializeUniqueCases(SwitchInst *SI, PHINode *&PHI, BasicBlock *&CommonDest,
52875287
static Value *ConvertTwoCaseSwitch(const SwitchCaseResultVectorTy &ResultVector,
52885288
Constant *DefaultResult, Value *Condition,
52895289
IRBuilder<> &Builder) {
5290-
assert(ResultVector.size() == 2 &&
5291-
"We should have exactly two unique results at this point");
52925290
// If we are selecting between only two cases transform into a simple
52935291
// select or a two-way select if default is possible.
5294-
if (ResultVector[0].second.size() == 1 &&
5292+
if (ResultVector.size() == 2 && ResultVector[0].second.size() == 1 &&
52955293
ResultVector[1].second.size() == 1) {
52965294
ConstantInt *const FirstCase = ResultVector[0].second[0];
52975295
ConstantInt *const SecondCase = ResultVector[1].second[0];
@@ -5310,6 +5308,17 @@ static Value *ConvertTwoCaseSwitch(const SwitchCaseResultVectorTy &ResultVector,
53105308
SelectValue, "switch.select");
53115309
}
53125310

5311+
// Handle the degenerate case where two cases have the same value.
5312+
if (ResultVector.size() == 1 && ResultVector[0].second.size() == 2 &&
5313+
DefaultResult) {
5314+
Value *Cmp1 = Builder.CreateICmpEQ(
5315+
Condition, ResultVector[0].second[0], "switch.selectcmp.case1");
5316+
Value *Cmp2 = Builder.CreateICmpEQ(
5317+
Condition, ResultVector[0].second[1], "switch.selectcmp.case2");
5318+
Value *Cmp = Builder.CreateOr(Cmp1, Cmp2, "switch.selectcmp");
5319+
return Builder.CreateSelect(Cmp, ResultVector[0].first, DefaultResult);
5320+
}
5321+
53135322
return nullptr;
53145323
}
53155324

@@ -5334,13 +5343,14 @@ static void RemoveSwitchAfterSelectConversion(SwitchInst *SI, PHINode *PHI,
53345343
PHI->removeIncomingValue(SelectBB);
53355344
PHI->addIncoming(SelectValue, SelectBB);
53365345

5346+
SmallPtrSet<BasicBlock *, 4> RemovedSuccessors;
53375347
for (unsigned i = 0, e = SI->getNumSuccessors(); i < e; ++i) {
53385348
BasicBlock *Succ = SI->getSuccessor(i);
53395349

53405350
if (Succ == DestBB)
53415351
continue;
53425352
Succ->removePredecessor(SelectBB);
5343-
if (DTU)
5353+
if (DTU && RemovedSuccessors.insert(Succ).second)
53445354
Updates.push_back({DominatorTree::Delete, SelectBB, Succ});
53455355
}
53465356
SI->eraseFromParent();
@@ -5361,10 +5371,8 @@ static bool switchToSelect(SwitchInst *SI, IRBuilder<> &Builder,
53615371
SwitchCaseResultVectorTy UniqueResults;
53625372
// Collect all the cases that will deliver the same value from the switch.
53635373
if (!InitializeUniqueCases(SI, PHI, CommonDest, UniqueResults, DefaultResult,
5364-
DL, TTI, 2, 1))
5365-
return false;
5366-
// Selects choose between maximum two values.
5367-
if (UniqueResults.size() != 2)
5374+
DL, TTI, /*MaxUniqueResults*/2,
5375+
/*MaxCasesPerResult*/2))
53685376
return false;
53695377
assert(PHI != nullptr && "PHI for value select not found");
53705378

llvm/test/Transforms/PhaseOrdering/partialord-ule.ll

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,8 @@
66
define i1 @ule(i32 %a, i32 %b) {
77
; CHECK-LABEL: @ule(
88
; CHECK-NEXT: start:
9-
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]]
10-
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[A]], [[B]]
11-
; CHECK-NEXT: [[CMP3:%.*]] = icmp ne i32 [[A]], [[B]]
12-
; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP3]] to i64
13-
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[CMP2]], i64 -1, i64 [[ZEXT]]
14-
; CHECK-NEXT: [[SEL2:%.*]] = select i1 [[CMP1]], i64 0, i64 [[SEL1]]
15-
; CHECK-NEXT: switch i64 [[SEL2]], label [[EXIT:%.*]] [
16-
; CHECK-NEXT: i64 -1, label [[BB:%.*]]
17-
; CHECK-NEXT: i64 0, label [[BB]]
18-
; CHECK-NEXT: ]
19-
; CHECK: bb:
20-
; CHECK-NEXT: br label [[EXIT]]
21-
; CHECK: exit:
22-
; CHECK-NEXT: [[RES:%.*]] = phi i1 [ true, [[BB]] ], [ false, [[START:%.*]] ]
23-
; CHECK-NEXT: ret i1 [[RES]]
9+
; CHECK-NEXT: [[DOTNOT:%.*]] = icmp ule i32 [[A:%.*]], [[B:%.*]]
10+
; CHECK-NEXT: ret i1 [[DOTNOT]]
2411
;
2512
start:
2613
%cmp1 = icmp eq i32 %a, %b

llvm/test/Transforms/SimplifyCFG/switch-to-select-two-case.ll

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,11 @@ return:
4444
define i32 @same_value(i32 %a) {
4545
; CHECK-LABEL: @same_value(
4646
; CHECK-NEXT: entry:
47-
; CHECK-NEXT: switch i32 [[A:%.*]], label [[SW_EPILOG:%.*]] [
48-
; CHECK-NEXT: i32 10, label [[RETURN:%.*]]
49-
; CHECK-NEXT: i32 20, label [[RETURN]]
50-
; CHECK-NEXT: ]
51-
; CHECK: sw.epilog:
52-
; CHECK-NEXT: br label [[RETURN]]
53-
; CHECK: return:
54-
; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ 4, [[SW_EPILOG]] ], [ 10, [[ENTRY:%.*]] ], [ 10, [[ENTRY]] ]
55-
; CHECK-NEXT: ret i32 [[RETVAL_0]]
47+
; CHECK-NEXT: [[SWITCH_SELECTCMP_CASE1:%.*]] = icmp eq i32 [[A:%.*]], 10
48+
; CHECK-NEXT: [[SWITCH_SELECTCMP_CASE2:%.*]] = icmp eq i32 [[A]], 20
49+
; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = or i1 [[SWITCH_SELECTCMP_CASE1]], [[SWITCH_SELECTCMP_CASE2]]
50+
; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[SWITCH_SELECTCMP]], i32 10, i32 4
51+
; CHECK-NEXT: ret i32 [[TMP0]]
5652
;
5753
entry:
5854
switch i32 %a, label %sw.epilog [

0 commit comments

Comments
 (0)