Skip to content

Commit 9934a5b

Browse files
committed
[CVP] processSwitch: Remove default case when switch cover all possible values.
Differential Revision: https://reviews.llvm.org/D106056
1 parent 3a063f5 commit 9934a5b

File tree

5 files changed

+92
-25
lines changed

5 files changed

+92
-25
lines changed

llvm/include/llvm/Transforms/Utils/Local.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class MDNode;
5555
class MemorySSAUpdater;
5656
class PHINode;
5757
class StoreInst;
58+
class SwitchInst;
5859
class TargetLibraryInfo;
5960
class TargetTransformInfo;
6061

@@ -236,6 +237,10 @@ CallInst *createCallMatchingInvoke(InvokeInst *II);
236237
/// This function converts the specified invoek into a normall call.
237238
void changeToCall(InvokeInst *II, DomTreeUpdater *DTU = nullptr);
238239

240+
/// This function removes the default destination from the specified switch.
241+
void createUnreachableSwitchDefault(SwitchInst *Switch,
242+
DomTreeUpdater *DTU = nullptr);
243+
239244
///===---------------------------------------------------------------------===//
240245
/// Dbg Intrinsic utilities
241246
///

llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,13 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI,
341341
// ConstantFoldTerminator() as the underlying SwitchInst can be changed.
342342
SwitchInstProfUpdateWrapper SI(*I);
343343

344-
for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) {
344+
APInt Low =
345+
APInt::getSignedMaxValue(Cond->getType()->getScalarSizeInBits());
346+
APInt High =
347+
APInt::getSignedMinValue(Cond->getType()->getScalarSizeInBits());
348+
349+
SwitchInst::CaseIt CI = SI->case_begin();
350+
for (auto CE = SI->case_end(); CI != CE;) {
345351
ConstantInt *Case = CI->getCaseValue();
346352
LazyValueInfo::Tristate State =
347353
LVI->getPredicateAt(CmpInst::ICMP_EQ, Cond, Case, I,
@@ -374,9 +380,28 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI,
374380
break;
375381
}
376382

383+
// Get Lower/Upper bound from switch cases.
384+
Low = APIntOps::smin(Case->getValue(), Low);
385+
High = APIntOps::smax(Case->getValue(), High);
386+
377387
// Increment the case iterator since we didn't delete it.
378388
++CI;
379389
}
390+
391+
// Try to simplify default case as unreachable
392+
if (CI == SI->case_end() && SI->getNumCases() != 0 &&
393+
!isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg())) {
394+
const ConstantRange SIRange =
395+
LVI->getConstantRange(SI->getCondition(), SI);
396+
397+
// If the numbered switch cases cover the entire range of the condition,
398+
// then the default case is not reachable.
399+
if (SIRange.getSignedMin() == Low && SIRange.getSignedMax() == High &&
400+
SI->getNumCases() == High - Low + 1) {
401+
createUnreachableSwitchDefault(SI, &DTU);
402+
Changed = true;
403+
}
404+
}
380405
}
381406

382407
if (Changed)

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,6 +2182,30 @@ void llvm::changeToCall(InvokeInst *II, DomTreeUpdater *DTU) {
21822182
DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDestBB}});
21832183
}
21842184

2185+
void llvm::createUnreachableSwitchDefault(SwitchInst *Switch,
2186+
DomTreeUpdater *DTU) {
2187+
LLVM_DEBUG(dbgs() << "Switch default is dead.\n");
2188+
auto *BB = Switch->getParent();
2189+
BasicBlock *NewDefaultBlock = SplitBlockPredecessors(
2190+
Switch->getDefaultDest(), Switch->getParent(), "", DTU);
2191+
auto *OrigDefaultBlock = Switch->getDefaultDest();
2192+
Switch->setDefaultDest(&*NewDefaultBlock);
2193+
if (DTU)
2194+
DTU->applyUpdates({{DominatorTree::Insert, BB, &*NewDefaultBlock},
2195+
{DominatorTree::Delete, BB, OrigDefaultBlock}});
2196+
2197+
SplitBlock(&*NewDefaultBlock, &NewDefaultBlock->front(), DTU);
2198+
SmallVector<DominatorTree::UpdateType, 2> Updates;
2199+
if (DTU)
2200+
for (auto *Successor : successors(NewDefaultBlock))
2201+
Updates.push_back({DominatorTree::Delete, NewDefaultBlock, Successor});
2202+
auto *NewTerminator = NewDefaultBlock->getTerminator();
2203+
new UnreachableInst(Switch->getContext(), NewTerminator);
2204+
NewTerminator->eraseFromParent();
2205+
if (DTU)
2206+
DTU->applyUpdates(Updates);
2207+
}
2208+
21852209
BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
21862210
BasicBlock *UnwindEdge,
21872211
DomTreeUpdater *DTU) {

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4743,29 +4743,6 @@ static bool CasesAreContiguous(SmallVectorImpl<ConstantInt *> &Cases) {
47434743
return true;
47444744
}
47454745

4746-
static void createUnreachableSwitchDefault(SwitchInst *Switch,
4747-
DomTreeUpdater *DTU) {
4748-
LLVM_DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
4749-
auto *BB = Switch->getParent();
4750-
BasicBlock *NewDefaultBlock = SplitBlockPredecessors(
4751-
Switch->getDefaultDest(), Switch->getParent(), "", DTU);
4752-
auto *OrigDefaultBlock = Switch->getDefaultDest();
4753-
Switch->setDefaultDest(&*NewDefaultBlock);
4754-
if (DTU)
4755-
DTU->applyUpdates({{DominatorTree::Insert, BB, &*NewDefaultBlock},
4756-
{DominatorTree::Delete, BB, OrigDefaultBlock}});
4757-
SplitBlock(&*NewDefaultBlock, &NewDefaultBlock->front(), DTU);
4758-
SmallVector<DominatorTree::UpdateType, 2> Updates;
4759-
if (DTU)
4760-
for (auto *Successor : successors(NewDefaultBlock))
4761-
Updates.push_back({DominatorTree::Delete, NewDefaultBlock, Successor});
4762-
auto *NewTerminator = NewDefaultBlock->getTerminator();
4763-
new UnreachableInst(Switch->getContext(), NewTerminator);
4764-
EraseTerminatorAndDCECond(NewTerminator);
4765-
if (DTU)
4766-
DTU->applyUpdates(Updates);
4767-
}
4768-
47694746
/// Turn a switch with two reachable destinations into an integer range
47704747
/// comparison and branch.
47714748
bool SimplifyCFGOpt::TurnSwitchRangeIntoICmp(SwitchInst *SI,

llvm/test/Transforms/CorrelatedValuePropagation/basic.ll

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ define i32 @switch_range(i32 %cond) {
382382
; CHECK-NEXT: entry:
383383
; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND:%.*]], 3
384384
; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1
385-
; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE:%.*]] [
385+
; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE1:%.*]] [
386386
; CHECK-NEXT: i32 1, label [[EXIT1:%.*]]
387387
; CHECK-NEXT: i32 2, label [[EXIT2:%.*]]
388388
; CHECK-NEXT: i32 3, label [[EXIT1]]
@@ -391,6 +391,10 @@ define i32 @switch_range(i32 %cond) {
391391
; CHECK-NEXT: ret i32 1
392392
; CHECK: exit2:
393393
; CHECK-NEXT: ret i32 2
394+
; CHECK: unreachable1:
395+
; CHECK-NEXT: unreachable
396+
; CHECK: unreachable1.split:
397+
; CHECK-NEXT: br label [[UNREACHABLE:%.*]]
394398
; CHECK: unreachable:
395399
; CHECK-NEXT: ret i32 0
396400
;
@@ -411,6 +415,38 @@ unreachable:
411415
ret i32 0
412416
}
413417

418+
define i32 @switch_range_not_full(i32 %cond) {
419+
; CHECK-LABEL: @switch_range_not_full(
420+
; CHECK-NEXT: entry:
421+
; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND:%.*]], 3
422+
; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1
423+
; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE:%.*]] [
424+
; CHECK-NEXT: i32 1, label [[EXIT1:%.*]]
425+
; CHECK-NEXT: i32 3, label [[EXIT2:%.*]]
426+
; CHECK-NEXT: ]
427+
; CHECK: exit1:
428+
; CHECK-NEXT: ret i32 1
429+
; CHECK: exit2:
430+
; CHECK-NEXT: ret i32 2
431+
; CHECK: unreachable:
432+
; CHECK-NEXT: ret i32 0
433+
;
434+
entry:
435+
%s = urem i32 %cond, 3
436+
%s1 = add i32 %s, 1
437+
switch i32 %s1, label %unreachable [
438+
i32 1, label %exit1
439+
i32 3, label %exit2
440+
]
441+
442+
exit1:
443+
ret i32 1
444+
exit2:
445+
ret i32 2
446+
unreachable:
447+
ret i32 0
448+
}
449+
414450
define i1 @arg_attribute(i8* nonnull %a) {
415451
; CHECK-LABEL: @arg_attribute(
416452
; CHECK-NEXT: ret i1 false

0 commit comments

Comments
 (0)