class MemorySSAUpdater;
class PHINode;
class StoreInst;
-class SwitchInst;
class TargetLibraryInfo;
class TargetTransformInfo;
/// This function converts the specified invoek into a normall call.
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
///
// ConstantFoldTerminator() as the underlying SwitchInst can be changed.
SwitchInstProfUpdateWrapper SI(*I);
- 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;) {
+ for (auto CI = SI->case_begin(), CE = SI->case_end(); CI != CE;) {
ConstantInt *Case = CI->getCaseValue();
LazyValueInfo::Tristate State =
LVI->getPredicateAt(CmpInst::ICMP_EQ, Cond, Case, I,
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.
++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)
DTU->applyUpdates({{DominatorTree::Delete, BB, UnwindDestBB}});
}
-void llvm::createUnreachableSwitchDefault(SwitchInst *Switch,
- DomTreeUpdater *DTU) {
- LLVM_DEBUG(dbgs() << "Switch default is dead.\n");
- auto *BB = Switch->getParent();
- BasicBlock *NewDefaultBlock = SplitBlockPredecessors(
- Switch->getDefaultDest(), Switch->getParent(), "", DTU);
- auto *OrigDefaultBlock = Switch->getDefaultDest();
- Switch->setDefaultDest(&*NewDefaultBlock);
- if (DTU)
- DTU->applyUpdates({{DominatorTree::Insert, BB, &*NewDefaultBlock},
- {DominatorTree::Delete, BB, OrigDefaultBlock}});
-
- SplitBlock(&*NewDefaultBlock, &NewDefaultBlock->front(), DTU);
- SmallVector<DominatorTree::UpdateType, 2> Updates;
- if (DTU)
- for (auto *Successor : successors(NewDefaultBlock))
- Updates.push_back({DominatorTree::Delete, NewDefaultBlock, Successor});
- auto *NewTerminator = NewDefaultBlock->getTerminator();
- new UnreachableInst(Switch->getContext(), NewTerminator);
- NewTerminator->eraseFromParent();
- if (DTU)
- DTU->applyUpdates(Updates);
-}
-
BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
BasicBlock *UnwindEdge,
DomTreeUpdater *DTU) {
return true;
}
+static void createUnreachableSwitchDefault(SwitchInst *Switch,
+ DomTreeUpdater *DTU) {
+ LLVM_DEBUG(dbgs() << "SimplifyCFG: switch default is dead.\n");
+ auto *BB = Switch->getParent();
+ BasicBlock *NewDefaultBlock = SplitBlockPredecessors(
+ Switch->getDefaultDest(), Switch->getParent(), "", DTU);
+ auto *OrigDefaultBlock = Switch->getDefaultDest();
+ Switch->setDefaultDest(&*NewDefaultBlock);
+ if (DTU)
+ DTU->applyUpdates({{DominatorTree::Insert, BB, &*NewDefaultBlock},
+ {DominatorTree::Delete, BB, OrigDefaultBlock}});
+ SplitBlock(&*NewDefaultBlock, &NewDefaultBlock->front(), DTU);
+ SmallVector<DominatorTree::UpdateType, 2> Updates;
+ if (DTU)
+ for (auto *Successor : successors(NewDefaultBlock))
+ Updates.push_back({DominatorTree::Delete, NewDefaultBlock, Successor});
+ auto *NewTerminator = NewDefaultBlock->getTerminator();
+ new UnreachableInst(Switch->getContext(), NewTerminator);
+ EraseTerminatorAndDCECond(NewTerminator);
+ if (DTU)
+ DTU->applyUpdates(Updates);
+}
+
/// Turn a switch with two reachable destinations into an integer range
/// comparison and branch.
bool SimplifyCFGOpt::TurnSwitchRangeIntoICmp(SwitchInst *SI,
; CHECK-NEXT: entry:
; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND:%.*]], 3
; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1
-; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE1:%.*]] [
+; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE:%.*]] [
; CHECK-NEXT: i32 1, label [[EXIT1:%.*]]
; CHECK-NEXT: i32 2, label [[EXIT2:%.*]]
; CHECK-NEXT: i32 3, label [[EXIT1]]
; CHECK-NEXT: ret i32 1
; CHECK: exit2:
; CHECK-NEXT: ret i32 2
-; CHECK: unreachable1:
-; CHECK-NEXT: unreachable
-; CHECK: unreachable1.split:
-; CHECK-NEXT: br label [[UNREACHABLE:%.*]]
; CHECK: unreachable:
; CHECK-NEXT: ret i32 0
;
ret i32 0
}
-define i32 @switch_range_not_full(i32 %cond) {
-; CHECK-LABEL: @switch_range_not_full(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[S:%.*]] = urem i32 [[COND:%.*]], 3
-; CHECK-NEXT: [[S1:%.*]] = add nuw nsw i32 [[S]], 1
-; CHECK-NEXT: switch i32 [[S1]], label [[UNREACHABLE:%.*]] [
-; CHECK-NEXT: i32 1, label [[EXIT1:%.*]]
-; CHECK-NEXT: i32 3, label [[EXIT2:%.*]]
-; CHECK-NEXT: ]
-; CHECK: exit1:
-; CHECK-NEXT: ret i32 1
-; CHECK: exit2:
-; CHECK-NEXT: ret i32 2
-; CHECK: unreachable:
-; CHECK-NEXT: ret i32 0
-;
-entry:
- %s = urem i32 %cond, 3
- %s1 = add i32 %s, 1
- switch i32 %s1, label %unreachable [
- i32 1, label %exit1
- i32 3, label %exit2
- ]
-
-exit1:
- ret i32 1
-exit2:
- ret i32 2
-unreachable:
- ret i32 0
-}
-
define i1 @arg_attribute(i8* nonnull %a) {
; CHECK-LABEL: @arg_attribute(
; CHECK-NEXT: ret i1 false