forked from OSchip/llvm-project
Revert "Revert "Recommit "Revert "[CVP] processSwitch: Remove default case when switch cover all possible values.""""
This reverts commit 3a998c06a8
.
This commit is contained in:
parent
b4fb42300e
commit
c93f93b2e3
|
@ -55,6 +55,7 @@ class MDNode;
|
||||||
class MemorySSAUpdater;
|
class MemorySSAUpdater;
|
||||||
class PHINode;
|
class PHINode;
|
||||||
class StoreInst;
|
class StoreInst;
|
||||||
|
class SwitchInst;
|
||||||
class TargetLibraryInfo;
|
class TargetLibraryInfo;
|
||||||
class TargetTransformInfo;
|
class TargetTransformInfo;
|
||||||
|
|
||||||
|
@ -237,6 +238,10 @@ CallInst *createCallMatchingInvoke(InvokeInst *II);
|
||||||
/// This function converts the specified invoek into a normall call.
|
/// This function converts the specified invoek into a normall call.
|
||||||
void changeToCall(InvokeInst *II, DomTreeUpdater *DTU = nullptr);
|
void changeToCall(InvokeInst *II, DomTreeUpdater *DTU = nullptr);
|
||||||
|
|
||||||
|
/// This function removes the default destination from the specified switch.
|
||||||
|
void createUnreachableSwitchDefault(SwitchInst *Switch,
|
||||||
|
DomTreeUpdater *DTU = nullptr);
|
||||||
|
|
||||||
///===---------------------------------------------------------------------===//
|
///===---------------------------------------------------------------------===//
|
||||||
/// Dbg Intrinsic utilities
|
/// Dbg Intrinsic utilities
|
||||||
///
|
///
|
||||||
|
|
|
@ -341,7 +341,13 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI,
|
||||||
// ConstantFoldTerminator() as the underlying SwitchInst can be changed.
|
// ConstantFoldTerminator() as the underlying SwitchInst can be changed.
|
||||||
SwitchInstProfUpdateWrapper SI(*I);
|
SwitchInstProfUpdateWrapper SI(*I);
|
||||||
|
|
||||||
for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) {
|
APInt Low =
|
||||||
|
APInt::getSignedMaxValue(Cond->getType()->getScalarSizeInBits());
|
||||||
|
APInt High =
|
||||||
|
APInt::getSignedMinValue(Cond->getType()->getScalarSizeInBits());
|
||||||
|
|
||||||
|
SwitchInst::CaseIt CI = SI->case_begin();
|
||||||
|
for (auto CE = SI->case_end(); CI != CE;) {
|
||||||
ConstantInt *Case = CI->getCaseValue();
|
ConstantInt *Case = CI->getCaseValue();
|
||||||
LazyValueInfo::Tristate State =
|
LazyValueInfo::Tristate State =
|
||||||
LVI->getPredicateAt(CmpInst::ICMP_EQ, Cond, Case, I,
|
LVI->getPredicateAt(CmpInst::ICMP_EQ, Cond, Case, I,
|
||||||
|
@ -374,9 +380,28 @@ static bool processSwitch(SwitchInst *I, LazyValueInfo *LVI,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get Lower/Upper bound from switch cases.
|
||||||
|
Low = APIntOps::smin(Case->getValue(), Low);
|
||||||
|
High = APIntOps::smax(Case->getValue(), High);
|
||||||
|
|
||||||
// Increment the case iterator since we didn't delete it.
|
// Increment the case iterator since we didn't delete it.
|
||||||
++CI;
|
++CI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to simplify default case as unreachable
|
||||||
|
if (CI == SI->case_end() && SI->getNumCases() != 0 &&
|
||||||
|
!isa<UnreachableInst>(SI->getDefaultDest()->getFirstNonPHIOrDbg())) {
|
||||||
|
const ConstantRange SIRange =
|
||||||
|
LVI->getConstantRange(SI->getCondition(), SI);
|
||||||
|
|
||||||
|
// If the numbered switch cases cover the entire range of the condition,
|
||||||
|
// then the default case is not reachable.
|
||||||
|
if (SIRange.getSignedMin() == Low && SIRange.getSignedMax() == High &&
|
||||||
|
SI->getNumCases() == High - Low + 1) {
|
||||||
|
createUnreachableSwitchDefault(SI, &DTU);
|
||||||
|
Changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Changed)
|
if (Changed)
|
||||||
|
|
|
@ -2190,6 +2190,26 @@ void llvm::changeToCall(InvokeInst *II, DomTreeUpdater *DTU) {
|
||||||
DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDestBB}});
|
DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDestBB}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void llvm::createUnreachableSwitchDefault(SwitchInst *Switch,
|
||||||
|
DomTreeUpdater *DTU) {
|
||||||
|
LLVM_DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
|
||||||
|
auto *BB = Switch->getParent();
|
||||||
|
auto *OrigDefaultBlock = Switch->getDefaultDest();
|
||||||
|
OrigDefaultBlock->removePredecessor(BB);
|
||||||
|
BasicBlock *NewDefaultBlock = BasicBlock::Create(
|
||||||
|
BB->getContext(), BB->getName() + ".unreachabledefault", BB->getParent(),
|
||||||
|
OrigDefaultBlock);
|
||||||
|
new UnreachableInst(Switch->getContext(), NewDefaultBlock);
|
||||||
|
Switch->setDefaultDest(&*NewDefaultBlock);
|
||||||
|
if (DTU) {
|
||||||
|
SmallVector<DominatorTree::UpdateType, 2> Updates;
|
||||||
|
Updates.push_back({DominatorTree::Insert, BB, &*NewDefaultBlock});
|
||||||
|
if (!is_contained(successors(BB), OrigDefaultBlock))
|
||||||
|
Updates.push_back({DominatorTree::Delete, BB, &*OrigDefaultBlock});
|
||||||
|
DTU->applyUpdates(Updates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
|
BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
|
||||||
BasicBlock *UnwindEdge,
|
BasicBlock *UnwindEdge,
|
||||||
DomTreeUpdater *DTU) {
|
DomTreeUpdater *DTU) {
|
||||||
|
|
|
@ -4782,26 +4782,6 @@ static bool CasesAreContiguous(SmallVectorImpl<ConstantInt *> &Cases) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void createUnreachableSwitchDefault(SwitchInst *Switch,
|
|
||||||
DomTreeUpdater *DTU) {
|
|
||||||
LLVM_DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
|
|
||||||
auto *BB = Switch->getParent();
|
|
||||||
auto *OrigDefaultBlock = Switch->getDefaultDest();
|
|
||||||
OrigDefaultBlock->removePredecessor(BB);
|
|
||||||
BasicBlock *NewDefaultBlock = BasicBlock::Create(
|
|
||||||
BB->getContext(), BB->getName() + ".unreachabledefault", BB->getParent(),
|
|
||||||
OrigDefaultBlock);
|
|
||||||
new UnreachableInst(Switch->getContext(), NewDefaultBlock);
|
|
||||||
Switch->setDefaultDest(&*NewDefaultBlock);
|
|
||||||
if (DTU) {
|
|
||||||
SmallVector<DominatorTree::UpdateType, 2> Updates;
|
|
||||||
Updates.push_back({DominatorTree::Insert, BB, &*NewDefaultBlock});
|
|
||||||
if (!is_contained(successors(BB), OrigDefaultBlock))
|
|
||||||
Updates.push_back({DominatorTree::Delete, BB, &*OrigDefaultBlock});
|
|
||||||
DTU->applyUpdates(Updates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Turn a switch with two reachable destinations into an integer range
|
/// Turn a switch with two reachable destinations into an integer range
|
||||||
/// comparison and branch.
|
/// comparison and branch.
|
||||||
bool SimplifyCFGOpt::TurnSwitchRangeIntoICmp(SwitchInst *SI,
|
bool SimplifyCFGOpt::TurnSwitchRangeIntoICmp(SwitchInst *SI,
|
||||||
|
|
|
@ -382,7 +382,7 @@ define i32 @switch_range(i32 %cond) {
|
||||||
; CHECK-NEXT: entry:
|
; CHECK-NEXT: entry:
|
||||||
; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND:%.*]], 3
|
; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND:%.*]], 3
|
||||||
; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1
|
; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1
|
||||||
; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE:%.*]] [
|
; CHECK-NEXT: switch i32 [[S1]], label [[ENTRY_UNREACHABLEDEFAULT:%.*]] [
|
||||||
; CHECK-NEXT: i32 1, label [[EXIT1:%.*]]
|
; CHECK-NEXT: i32 1, label [[EXIT1:%.*]]
|
||||||
; CHECK-NEXT: i32 2, label [[EXIT2:%.*]]
|
; CHECK-NEXT: i32 2, label [[EXIT2:%.*]]
|
||||||
; CHECK-NEXT: i32 3, label [[EXIT1]]
|
; CHECK-NEXT: i32 3, label [[EXIT1]]
|
||||||
|
@ -391,6 +391,8 @@ define i32 @switch_range(i32 %cond) {
|
||||||
; CHECK-NEXT: ret i32 1
|
; CHECK-NEXT: ret i32 1
|
||||||
; CHECK: exit2:
|
; CHECK: exit2:
|
||||||
; CHECK-NEXT: ret i32 2
|
; CHECK-NEXT: ret i32 2
|
||||||
|
; CHECK: entry.unreachabledefault:
|
||||||
|
; CHECK-NEXT: unreachable
|
||||||
; CHECK: unreachable:
|
; CHECK: unreachable:
|
||||||
; CHECK-NEXT: ret i32 0
|
; CHECK-NEXT: ret i32 0
|
||||||
;
|
;
|
||||||
|
@ -453,10 +455,9 @@ define i8 @switch_defaultdest_multipleuse(i8 %t0) {
|
||||||
; CHECK-NEXT: entry:
|
; CHECK-NEXT: entry:
|
||||||
; CHECK-NEXT: [[O:%.*]] = or i8 [[T0:%.*]], 1
|
; CHECK-NEXT: [[O:%.*]] = or i8 [[T0:%.*]], 1
|
||||||
; CHECK-NEXT: [[R:%.*]] = srem i8 1, [[O]]
|
; CHECK-NEXT: [[R:%.*]] = srem i8 1, [[O]]
|
||||||
; CHECK-NEXT: switch i8 [[R]], label [[EXIT:%.*]] [
|
; CHECK-NEXT: br label [[EXIT:%.*]]
|
||||||
; CHECK-NEXT: i8 0, label [[EXIT]]
|
; CHECK: entry.unreachabledefault:
|
||||||
; CHECK-NEXT: i8 1, label [[EXIT]]
|
; CHECK-NEXT: unreachable
|
||||||
; CHECK-NEXT: ]
|
|
||||||
; CHECK: exit:
|
; CHECK: exit:
|
||||||
; CHECK-NEXT: ret i8 0
|
; CHECK-NEXT: ret i8 0
|
||||||
;
|
;
|
||||||
|
|
Loading…
Reference in New Issue