233 changes: 185 additions & 48 deletions llvm/lib/Transforms/Utils/BasicBlockUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,12 +542,16 @@ llvm::SplitAllCriticalEdges(Function &F,
return NumBroken;
}

BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt,
DominatorTree *DT, LoopInfo *LI,
MemorySSAUpdater *MSSAU, const Twine &BBName,
bool Before) {
if (Before)
return splitBlockBefore(Old, SplitPt, DT, LI, MSSAU, BBName);
static BasicBlock *SplitBlockImpl(BasicBlock *Old, Instruction *SplitPt,
DomTreeUpdater *DTU, DominatorTree *DT,
LoopInfo *LI, MemorySSAUpdater *MSSAU,
const Twine &BBName, bool Before) {
if (Before) {
DomTreeUpdater LocalDTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
return splitBlockBefore(Old, SplitPt,
DTU ? DTU : (DT ? &LocalDTU : nullptr), LI, MSSAU,
BBName);
}
BasicBlock::iterator SplitIt = SplitPt->getIterator();
while (isa<PHINode>(SplitIt) || SplitIt->isEHPad())
++SplitIt;
Expand All @@ -561,7 +565,20 @@ BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt,
if (Loop *L = LI->getLoopFor(Old))
L->addBasicBlockToLoop(New, *LI);

if (DT)
if (DTU) {
SmallVector<DominatorTree::UpdateType, 8> Updates;
// Old dominates New. New node dominates all other nodes dominated by Old.
SmallSetVector<BasicBlock *, 8> UniqueSuccessorsOfOld(succ_begin(New),
succ_end(New));
Updates.push_back({DominatorTree::Insert, Old, New});
Updates.reserve(Updates.size() + 2 * UniqueSuccessorsOfOld.size());
for (BasicBlock *UniqueSuccessorOfOld : UniqueSuccessorsOfOld) {
Updates.push_back({DominatorTree::Insert, New, UniqueSuccessorOfOld});
Updates.push_back({DominatorTree::Delete, Old, UniqueSuccessorOfOld});
}

DTU->applyUpdates(Updates);
} else if (DT)
// Old dominates New. New node dominates all other nodes dominated by Old.
if (DomTreeNode *OldNode = DT->getNode(Old)) {
std::vector<DomTreeNode *> Children(OldNode->begin(), OldNode->end());
Expand All @@ -579,8 +596,23 @@ BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt,
return New;
}

BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt,
DominatorTree *DT, LoopInfo *LI,
MemorySSAUpdater *MSSAU, const Twine &BBName,
bool Before) {
return SplitBlockImpl(Old, SplitPt, /*DTU=*/nullptr, DT, LI, MSSAU, BBName,
Before);
}
BasicBlock *llvm::SplitBlock(BasicBlock *Old, Instruction *SplitPt,
DomTreeUpdater *DTU, LoopInfo *LI,
MemorySSAUpdater *MSSAU, const Twine &BBName,
bool Before) {
return SplitBlockImpl(Old, SplitPt, DTU, /*DT=*/nullptr, LI, MSSAU, BBName,
Before);
}

BasicBlock *llvm::splitBlockBefore(BasicBlock *Old, Instruction *SplitPt,
DominatorTree *DT, LoopInfo *LI,
DomTreeUpdater *DTU, LoopInfo *LI,
MemorySSAUpdater *MSSAU,
const Twine &BBName) {

Expand All @@ -598,25 +630,25 @@ BasicBlock *llvm::splitBlockBefore(BasicBlock *Old, Instruction *SplitPt,
if (Loop *L = LI->getLoopFor(Old))
L->addBasicBlockToLoop(New, *LI);

if (DT) {
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
if (DTU) {
SmallVector<DominatorTree::UpdateType, 8> DTUpdates;
// New dominates Old. The predecessor nodes of the Old node dominate
// New node.
SmallSetVector<BasicBlock *, 8> UniquePredecessorsOfOld(pred_begin(New),
pred_end(New));
DTUpdates.push_back({DominatorTree::Insert, New, Old});
for (BasicBlock *Pred : predecessors(New))
if (DT->getNode(Pred)) {
DTUpdates.push_back({DominatorTree::Insert, Pred, New});
DTUpdates.push_back({DominatorTree::Delete, Pred, Old});
}
DTUpdates.reserve(DTUpdates.size() + 2 * UniquePredecessorsOfOld.size());
for (BasicBlock *UniquePredecessorOfOld : UniquePredecessorsOfOld) {
DTUpdates.push_back({DominatorTree::Insert, UniquePredecessorOfOld, New});
DTUpdates.push_back({DominatorTree::Delete, UniquePredecessorOfOld, Old});
}

DTU.applyUpdates(DTUpdates);
DTU.flush();
DTU->applyUpdates(DTUpdates);

// Move MemoryAccesses still tracked in Old, but part of New now.
// Update accesses in successor blocks accordingly.
if (MSSAU) {
MSSAU->applyUpdates(DTUpdates, *DT);
MSSAU->applyUpdates(DTUpdates, DTU->getDomTree());
if (VerifyMemorySSA)
MSSAU->getMemorySSA()->verifyMemorySSA();
}
Expand All @@ -627,11 +659,31 @@ BasicBlock *llvm::splitBlockBefore(BasicBlock *Old, Instruction *SplitPt,
/// Update DominatorTree, LoopInfo, and LCCSA analysis information.
static void UpdateAnalysisInformation(BasicBlock *OldBB, BasicBlock *NewBB,
ArrayRef<BasicBlock *> Preds,
DominatorTree *DT, LoopInfo *LI,
MemorySSAUpdater *MSSAU,
DomTreeUpdater *DTU, DominatorTree *DT,
LoopInfo *LI, MemorySSAUpdater *MSSAU,
bool PreserveLCSSA, bool &HasLoopExit) {
// Update dominator tree if available.
if (DT) {
if (DTU) {
// Recalculation of DomTree is needed when updating a forward DomTree and
// the Entry BB is replaced.
if (NewBB == &NewBB->getParent()->getEntryBlock() && DTU->hasDomTree()) {
// The entry block was removed and there is no external interface for
// the dominator tree to be notified of this change. In this corner-case
// we recalculate the entire tree.
DTU->recalculate(*NewBB->getParent());
} else {
// Split block expects NewBB to have a non-empty set of predecessors.
SmallVector<DominatorTree::UpdateType, 8> Updates;
SmallSetVector<BasicBlock *, 8> UniquePreds(Preds.begin(), Preds.end());
Updates.push_back({DominatorTree::Insert, NewBB, OldBB});
Updates.reserve(Updates.size() + 2 * UniquePreds.size());
for (auto *UniquePred : UniquePreds) {
Updates.push_back({DominatorTree::Insert, UniquePred, NewBB});
Updates.push_back({DominatorTree::Delete, UniquePred, OldBB});
}
DTU->applyUpdates(Updates);
}
} else if (DT) {
if (OldBB == DT->getRootNode()->getBlock()) {
assert(NewBB == &NewBB->getParent()->getEntryBlock());
DT->setNewRoot(NewBB);
Expand All @@ -649,6 +701,8 @@ static void UpdateAnalysisInformation(BasicBlock *OldBB, BasicBlock *NewBB,
if (!LI)
return;

if (DTU && DTU->hasDomTree())
DT = &DTU->getDomTree();
assert(DT && "DT should be available to update LoopInfo!");
Loop *L = LI->getLoopFor(OldBB);

Expand Down Expand Up @@ -782,11 +836,17 @@ static void UpdatePHINodes(BasicBlock *OrigBB, BasicBlock *NewBB,
}
}

BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
ArrayRef<BasicBlock *> Preds,
const char *Suffix, DominatorTree *DT,
LoopInfo *LI, MemorySSAUpdater *MSSAU,
bool PreserveLCSSA) {
static void SplitLandingPadPredecessorsImpl(
BasicBlock *OrigBB, ArrayRef<BasicBlock *> Preds, const char *Suffix1,
const char *Suffix2, SmallVectorImpl<BasicBlock *> &NewBBs,
DomTreeUpdater *DTU, DominatorTree *DT, LoopInfo *LI,
MemorySSAUpdater *MSSAU, bool PreserveLCSSA);

static BasicBlock *
SplitBlockPredecessorsImpl(BasicBlock *BB, ArrayRef<BasicBlock *> Preds,
const char *Suffix, DomTreeUpdater *DTU,
DominatorTree *DT, LoopInfo *LI,
MemorySSAUpdater *MSSAU, bool PreserveLCSSA) {
// Do not attempt to split that which cannot be split.
if (!BB->canSplitPredecessors())
return nullptr;
Expand All @@ -797,8 +857,8 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
SmallVector<BasicBlock*, 2> NewBBs;
std::string NewName = std::string(Suffix) + ".split-lp";

SplitLandingPadPredecessors(BB, Preds, Suffix, NewName.c_str(), NewBBs, DT,
LI, MSSAU, PreserveLCSSA);
SplitLandingPadPredecessorsImpl(BB, Preds, Suffix, NewName.c_str(), NewBBs,
DTU, DT, LI, MSSAU, PreserveLCSSA);
return NewBBs[0];
}

Expand Down Expand Up @@ -850,7 +910,7 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,

// Update DominatorTree, LoopInfo, and LCCSA analysis information.
bool HasLoopExit = false;
UpdateAnalysisInformation(BB, NewBB, Preds, DT, LI, MSSAU, PreserveLCSSA,
UpdateAnalysisInformation(BB, NewBB, Preds, DTU, DT, LI, MSSAU, PreserveLCSSA,
HasLoopExit);

if (!Preds.empty()) {
Expand All @@ -870,13 +930,29 @@ BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
return NewBB;
}

void llvm::SplitLandingPadPredecessors(BasicBlock *OrigBB,
ArrayRef<BasicBlock *> Preds,
const char *Suffix1, const char *Suffix2,
SmallVectorImpl<BasicBlock *> &NewBBs,
DominatorTree *DT, LoopInfo *LI,
MemorySSAUpdater *MSSAU,
bool PreserveLCSSA) {
BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
ArrayRef<BasicBlock *> Preds,
const char *Suffix, DominatorTree *DT,
LoopInfo *LI, MemorySSAUpdater *MSSAU,
bool PreserveLCSSA) {
return SplitBlockPredecessorsImpl(BB, Preds, Suffix, /*DTU=*/nullptr, DT, LI,
MSSAU, PreserveLCSSA);
}
BasicBlock *llvm::SplitBlockPredecessors(BasicBlock *BB,
ArrayRef<BasicBlock *> Preds,
const char *Suffix,
DomTreeUpdater *DTU, LoopInfo *LI,
MemorySSAUpdater *MSSAU,
bool PreserveLCSSA) {
return SplitBlockPredecessorsImpl(BB, Preds, Suffix, DTU,
/*DT=*/nullptr, LI, MSSAU, PreserveLCSSA);
}

static void SplitLandingPadPredecessorsImpl(
BasicBlock *OrigBB, ArrayRef<BasicBlock *> Preds, const char *Suffix1,
const char *Suffix2, SmallVectorImpl<BasicBlock *> &NewBBs,
DomTreeUpdater *DTU, DominatorTree *DT, LoopInfo *LI,
MemorySSAUpdater *MSSAU, bool PreserveLCSSA) {
assert(OrigBB->isLandingPad() && "Trying to split a non-landing pad!");

// Create a new basic block for OrigBB's predecessors listed in Preds. Insert
Expand All @@ -901,8 +977,8 @@ void llvm::SplitLandingPadPredecessors(BasicBlock *OrigBB,
}

bool HasLoopExit = false;
UpdateAnalysisInformation(OrigBB, NewBB1, Preds, DT, LI, MSSAU, PreserveLCSSA,
HasLoopExit);
UpdateAnalysisInformation(OrigBB, NewBB1, Preds, DTU, DT, LI, MSSAU,
PreserveLCSSA, HasLoopExit);

// Update the PHI nodes in OrigBB with the values coming from NewBB1.
UpdatePHINodes(OrigBB, NewBB1, Preds, BI1, HasLoopExit);
Expand Down Expand Up @@ -937,7 +1013,7 @@ void llvm::SplitLandingPadPredecessors(BasicBlock *OrigBB,

// Update DominatorTree, LoopInfo, and LCCSA analysis information.
HasLoopExit = false;
UpdateAnalysisInformation(OrigBB, NewBB2, NewBB2Preds, DT, LI, MSSAU,
UpdateAnalysisInformation(OrigBB, NewBB2, NewBB2Preds, DTU, DT, LI, MSSAU,
PreserveLCSSA, HasLoopExit);

// Update the PHI nodes in OrigBB with the values coming from NewBB2.
Expand Down Expand Up @@ -974,6 +1050,29 @@ void llvm::SplitLandingPadPredecessors(BasicBlock *OrigBB,
}
}

void llvm::SplitLandingPadPredecessors(BasicBlock *OrigBB,
ArrayRef<BasicBlock *> Preds,
const char *Suffix1, const char *Suffix2,
SmallVectorImpl<BasicBlock *> &NewBBs,
DominatorTree *DT, LoopInfo *LI,
MemorySSAUpdater *MSSAU,
bool PreserveLCSSA) {
return SplitLandingPadPredecessorsImpl(
OrigBB, Preds, Suffix1, Suffix2, NewBBs,
/*DTU=*/nullptr, DT, LI, MSSAU, PreserveLCSSA);
}
void llvm::SplitLandingPadPredecessors(BasicBlock *OrigBB,
ArrayRef<BasicBlock *> Preds,
const char *Suffix1, const char *Suffix2,
SmallVectorImpl<BasicBlock *> &NewBBs,
DomTreeUpdater *DTU, LoopInfo *LI,
MemorySSAUpdater *MSSAU,
bool PreserveLCSSA) {
return SplitLandingPadPredecessorsImpl(OrigBB, Preds, Suffix1, Suffix2,
NewBBs, DTU, /*DT=*/nullptr, LI, MSSAU,
PreserveLCSSA);
}

ReturnInst *llvm::FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB,
BasicBlock *Pred,
DomTreeUpdater *DTU) {
Expand Down Expand Up @@ -1033,14 +1132,24 @@ ReturnInst *llvm::FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB,
return cast<ReturnInst>(NewRet);
}

Instruction *llvm::SplitBlockAndInsertIfThen(Value *Cond,
Instruction *SplitBefore,
bool Unreachable,
MDNode *BranchWeights,
DominatorTree *DT, LoopInfo *LI,
BasicBlock *ThenBlock) {
static Instruction *
SplitBlockAndInsertIfThenImpl(Value *Cond, Instruction *SplitBefore,
bool Unreachable, MDNode *BranchWeights,
DomTreeUpdater *DTU, DominatorTree *DT,
LoopInfo *LI, BasicBlock *ThenBlock) {
SmallVector<DominatorTree::UpdateType, 8> Updates;
BasicBlock *Head = SplitBefore->getParent();
BasicBlock *Tail = Head->splitBasicBlock(SplitBefore->getIterator());
if (DTU) {
SmallSetVector<BasicBlock *, 8> UniqueSuccessorsOfHead(succ_begin(Tail),
succ_end(Tail));
Updates.push_back({DominatorTree::Insert, Head, Tail});
Updates.reserve(Updates.size() + 2 * UniqueSuccessorsOfHead.size());
for (BasicBlock *UniqueSuccessorOfHead : UniqueSuccessorsOfHead) {
Updates.push_back({DominatorTree::Insert, Tail, UniqueSuccessorOfHead});
Updates.push_back({DominatorTree::Delete, Head, UniqueSuccessorOfHead});
}
}
Instruction *HeadOldTerm = Head->getTerminator();
LLVMContext &C = Head->getContext();
Instruction *CheckTerm;
Expand All @@ -1049,17 +1158,24 @@ Instruction *llvm::SplitBlockAndInsertIfThen(Value *Cond,
ThenBlock = BasicBlock::Create(C, "", Head->getParent(), Tail);
if (Unreachable)
CheckTerm = new UnreachableInst(C, ThenBlock);
else
else {
CheckTerm = BranchInst::Create(Tail, ThenBlock);
if (DTU)
Updates.push_back({DominatorTree::Insert, ThenBlock, Tail});
}
CheckTerm->setDebugLoc(SplitBefore->getDebugLoc());
} else
CheckTerm = ThenBlock->getTerminator();
BranchInst *HeadNewTerm =
BranchInst::Create(/*ifTrue*/ThenBlock, /*ifFalse*/Tail, Cond);
BranchInst::Create(/*ifTrue*/ ThenBlock, /*ifFalse*/ Tail, Cond);
if (DTU)
Updates.push_back({DominatorTree::Insert, Head, ThenBlock});
HeadNewTerm->setMetadata(LLVMContext::MD_prof, BranchWeights);
ReplaceInstWithInst(HeadOldTerm, HeadNewTerm);

if (DT) {
if (DTU)
DTU->applyUpdates(Updates);
else if (DT) {
if (DomTreeNode *OldNode = DT->getNode(Head)) {
std::vector<DomTreeNode *> Children(OldNode->begin(), OldNode->end());

Expand All @@ -1085,6 +1201,27 @@ Instruction *llvm::SplitBlockAndInsertIfThen(Value *Cond,
return CheckTerm;
}

Instruction *llvm::SplitBlockAndInsertIfThen(Value *Cond,
Instruction *SplitBefore,
bool Unreachable,
MDNode *BranchWeights,
DominatorTree *DT, LoopInfo *LI,
BasicBlock *ThenBlock) {
return SplitBlockAndInsertIfThenImpl(Cond, SplitBefore, Unreachable,
BranchWeights,
/*DTU=*/nullptr, DT, LI, ThenBlock);
}
Instruction *llvm::SplitBlockAndInsertIfThen(Value *Cond,
Instruction *SplitBefore,
bool Unreachable,
MDNode *BranchWeights,
DomTreeUpdater *DTU, LoopInfo *LI,
BasicBlock *ThenBlock) {
return SplitBlockAndInsertIfThenImpl(Cond, SplitBefore, Unreachable,
BranchWeights, DTU, /*DT=*/nullptr, LI,
ThenBlock);
}

void llvm::SplitBlockAndInsertIfThenElse(Value *Cond, Instruction *SplitBefore,
Instruction **ThenTerm,
Instruction **ElseTerm,
Expand Down
44 changes: 22 additions & 22 deletions llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(Instruction *TI,
if (!SafeToMergeTerminators(TI, PTI, &FailBlocks)) {
for (auto *Succ : FailBlocks) {
if (!SplitBlockPredecessors(Succ, TI->getParent(), ".fold.split",
DTU ? &DTU->getDomTree() : nullptr))
DTU))
return false;
}
}
Expand Down Expand Up @@ -1977,8 +1977,7 @@ static bool SinkCommonCodeFromPredecessors(BasicBlock *BB,
LLVM_DEBUG(dbgs() << "SINK: Splitting edge\n");
// We have a conditional edge and we're going to sink some instructions.
// Insert a new block postdominating all blocks we're going to sink from.
if (!SplitBlockPredecessors(BB, UnconditionalPreds, ".sink.split",
DTU ? &DTU->getDomTree() : nullptr))
if (!SplitBlockPredecessors(BB, UnconditionalPreds, ".sink.split", DTU))
// Edges couldn't be split.
return false;
Changed = true;
Expand Down Expand Up @@ -3391,8 +3390,7 @@ static bool mergeConditionalStoreToAddress(
// branch to QFB and PostBB.
BasicBlock *TruePred = QTB ? QTB : QFB->getSinglePredecessor();
BasicBlock *NewBB =
SplitBlockPredecessors(PostBB, {QFB, TruePred}, "condstore.split",
DTU ? &DTU->getDomTree() : nullptr);
SplitBlockPredecessors(PostBB, {QFB, TruePred}, "condstore.split", DTU);
if (!NewBB)
return false;
PostBB = NewBB;
Expand Down Expand Up @@ -3421,9 +3419,9 @@ static bool mergeConditionalStoreToAddress(
QPred = QB.CreateNot(QPred);
Value *CombinedPred = QB.CreateOr(PPred, QPred);

auto *T = SplitBlockAndInsertIfThen(
CombinedPred, &*QB.GetInsertPoint(), /*Unreachable=*/false,
/*BranchWeights=*/nullptr, DTU ? &DTU->getDomTree() : nullptr);
auto *T = SplitBlockAndInsertIfThen(CombinedPred, &*QB.GetInsertPoint(),
/*Unreachable=*/false,
/*BranchWeights=*/nullptr, DTU);
QB.SetInsertPoint(T);
StoreInst *SI = cast<StoreInst>(QB.CreateStore(QPHI, Address));
AAMDNodes AAMD;
Expand Down Expand Up @@ -4187,9 +4185,8 @@ bool SimplifyCFGOpt::SimplifyBranchOnICmpChain(BranchInst *BI,
// then we evaluate them with an explicit branch first. Split the block
// right before the condbr to handle it.
if (ExtraCase) {
BasicBlock *NewBB =
SplitBlock(BB, BI, DTU ? &DTU->getDomTree() : nullptr, /*LI=*/nullptr,
/*MSSAU=*/nullptr, "switch.early.test");
BasicBlock *NewBB = SplitBlock(BB, BI, DTU, /*LI=*/nullptr,
/*MSSAU=*/nullptr, "switch.early.test");

// Remove the uncond branch added to the old block.
Instruction *OldTI = BB->getTerminator();
Expand Down Expand Up @@ -4828,16 +4825,14 @@ 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 ? &DTU->getDomTree() : nullptr);
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 ? &DTU->getDomTree() : nullptr);
SplitBlock(&*NewDefaultBlock, &NewDefaultBlock->front(), DTU);
SmallVector<DominatorTree::UpdateType, 2> Updates;
for (auto *Successor : successors(NewDefaultBlock))
Updates.push_back({DominatorTree::Delete, NewDefaultBlock, Successor});
Expand Down Expand Up @@ -5399,20 +5394,25 @@ static void RemoveSwitchAfterSelectConversion(SwitchInst *SI, PHINode *PHI,
Value *SelectValue,
IRBuilder<> &Builder,
DomTreeUpdater *DTU) {
std::vector<DominatorTree::UpdateType> Updates;

BasicBlock *SelectBB = SI->getParent();
BasicBlock *DestBB = PHI->getParent();

if (!is_contained(predecessors(DestBB), SelectBB))
Updates.push_back({DominatorTree::Insert, SelectBB, DestBB});
Builder.CreateBr(DestBB);

// Remove the switch.

while (PHI->getBasicBlockIndex(SelectBB) >= 0)
PHI->removeIncomingValue(SelectBB);
PHI->addIncoming(SelectValue, SelectBB);

Builder.CreateBr(PHI->getParent());

std::vector<DominatorTree::UpdateType> Updates;

// Remove the switch.
for (unsigned i = 0, e = SI->getNumSuccessors(); i < e; ++i) {
BasicBlock *Succ = SI->getSuccessor(i);

if (Succ == PHI->getParent())
if (Succ == DestBB)
continue;
Succ->removePredecessor(SelectBB);
Updates.push_back({DominatorTree::Delete, SelectBB, Succ});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -sink-common-insts=1 < %s | FileCheck %s

declare void @widget(i8)

define void @baz(i8 %arg, i8 %arg10, i1 %arg11) {
; CHECK-LABEL: @baz(
; CHECK-NEXT: bb:
; CHECK-NEXT: br label [[BB12:%.*]]
; CHECK: bb12:
; CHECK-NEXT: [[TMP:%.*]] = icmp eq i8 [[ARG:%.*]], 0
; CHECK-NEXT: br i1 [[TMP]], label [[BB17:%.*]], label [[BB13:%.*]]
; CHECK: bb13:
; CHECK-NEXT: tail call void @widget(i8 11)
; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i8 [[ARG10:%.*]], 73
; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP]], i8 44, i8 22
; CHECK-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i8 [[ARG10]], 68
; CHECK-NEXT: [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP1]], i8 33, i8 [[SWITCH_SELECT]]
; CHECK-NEXT: tail call void @widget(i8 [[SWITCH_SELECT2]])
; CHECK-NEXT: br label [[BB17]]
; CHECK: bb17:
; CHECK-NEXT: br i1 [[ARG11:%.*]], label [[BB12]], label [[BB18:%.*]]
; CHECK: bb18:
; CHECK-NEXT: ret void
;
bb:
br label %bb12

bb12: ; preds = %bb17, %bb
%tmp = icmp eq i8 %arg, 0
br i1 %tmp, label %bb17, label %bb13

bb13: ; preds = %bb12
tail call void @widget(i8 11)
switch i8 %arg10, label %bb14 [
i8 68, label %bb15
i8 73, label %bb16
]

bb14: ; preds = %bb13
tail call void @widget(i8 22)
br label %bb17

bb15: ; preds = %bb13
tail call void @widget(i8 33)
br label %bb17

bb16: ; preds = %bb13
tail call void @widget(i8 44)
br label %bb17

bb17: ; preds = %bb16, %bb15, %bb14, %bb12
br i1 %arg11, label %bb12, label %bb18

bb18: ; preds = %bb17
ret void
}