Skip to content

Commit 8ba2adc

Browse files
committed
Recommit "Revert "[CVP] processSwitch: Remove default case when switch cover all possible values.""
Differential Revision: https://reviews.llvm.org/D106056
1 parent d1280f6 commit 8ba2adc

File tree

5 files changed

+57
-26
lines changed

5 files changed

+57
-26
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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,6 +2182,26 @@ 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() << "SimplifyCFG: switch default is dead.\n");
2188+
auto *BB = Switch->getParent();
2189+
auto *OrigDefaultBlock = Switch->getDefaultDest();
2190+
OrigDefaultBlock->removePredecessor(BB);
2191+
BasicBlock *NewDefaultBlock = BasicBlock::Create(
2192+
BB->getContext(), BB->getName() + ".unreachabledefault", BB->getParent(),
2193+
OrigDefaultBlock);
2194+
new UnreachableInst(Switch->getContext(), NewDefaultBlock);
2195+
Switch->setDefaultDest(&*NewDefaultBlock);
2196+
if (DTU) {
2197+
SmallVector<DominatorTree::UpdateType, 2> Updates;
2198+
Updates.push_back({DominatorTree::Insert, BB, &*NewDefaultBlock});
2199+
if (!is_contained(successors(BB), OrigDefaultBlock))
2200+
Updates.push_back({DominatorTree::Delete, BB, &*OrigDefaultBlock});
2201+
DTU->applyUpdates(Updates);
2202+
}
2203+
}
2204+
21852205
BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
21862206
BasicBlock *UnwindEdge,
21872207
DomTreeUpdater *DTU) {

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4743,26 +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-
auto *OrigDefaultBlock = Switch->getDefaultDest();
4751-
OrigDefaultBlock->removePredecessor(BB);
4752-
BasicBlock *NewDefaultBlock = BasicBlock::Create(
4753-
BB->getContext(), BB->getName() + ".unreachabledefault", BB->getParent(),
4754-
OrigDefaultBlock);
4755-
new UnreachableInst(Switch->getContext(), NewDefaultBlock);
4756-
Switch->setDefaultDest(&*NewDefaultBlock);
4757-
if (DTU) {
4758-
SmallVector<DominatorTree::UpdateType, 2> Updates;
4759-
Updates.push_back({DominatorTree::Insert, BB, &*NewDefaultBlock});
4760-
if (!is_contained(successors(BB), OrigDefaultBlock))
4761-
Updates.push_back({DominatorTree::Delete, BB, &*OrigDefaultBlock});
4762-
DTU->applyUpdates(Updates);
4763-
}
4764-
}
4765-
47664746
/// Turn a switch with two reachable destinations into an integer range
47674747
/// comparison and branch.
47684748
bool SimplifyCFGOpt::TurnSwitchRangeIntoICmp(SwitchInst *SI,

llvm/test/Transforms/CorrelatedValuePropagation/basic.ll

Lines changed: 6 additions & 5 deletions
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 [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
386386
; CHECK-NEXT: i32 1, label [[EXIT1:%.*]]
387387
; CHECK-NEXT: i32 2, label [[EXIT2:%.*]]
388388
; CHECK-NEXT: i32 3, label [[EXIT1]]
@@ -391,6 +391,8 @@ define i32 @switch_range(i32 %cond) {
391391
; CHECK-NEXT: ret i32 1
392392
; CHECK: exit2:
393393
; CHECK-NEXT: ret i32 2
394+
; CHECK: entry.unreachabledefault:
395+
; CHECK-NEXT: unreachable
394396
; CHECK: unreachable:
395397
; CHECK-NEXT: ret i32 0
396398
;
@@ -453,10 +455,9 @@ define i8 @switch_defaultdest_multipleuse(i8 %t0) {
453455
; CHECK-NEXT: entry:
454456
; CHECK-NEXT: [[O:%.*]] = or i8 [[T0:%.*]], 1
455457
; CHECK-NEXT: [[R:%.*]] = srem i8 1, [[O]]
456-
; CHECK-NEXT: switch i8 [[R]], label [[EXIT:%.*]] [
457-
; CHECK-NEXT: i8 0, label [[EXIT]]
458-
; CHECK-NEXT: i8 1, label [[EXIT]]
459-
; CHECK-NEXT: ]
458+
; CHECK-NEXT: br label [[EXIT:%.*]]
459+
; CHECK: entry.unreachabledefault:
460+
; CHECK-NEXT: unreachable
460461
; CHECK: exit:
461462
; CHECK-NEXT: ret i8 0
462463
;

0 commit comments

Comments
 (0)