Skip to content

Commit 2d07414

Browse files
committed
[SimplifyCFG] Teach simplifyUnreachable() to preserve DomTree
Pretty boring, removeUnwindEdge() already known how to update DomTree, so if we are to call it, we must first flush our own pending updates; otherwise, we just stop predecessors from branching to us, and for certain predecessors, stop their predecessors from branching to them also.
1 parent 2ee7248 commit 2d07414

File tree

12 files changed

+56
-23
lines changed

12 files changed

+56
-23
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4479,9 +4479,12 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
44794479
if (&BB->front() != UI)
44804480
return Changed;
44814481

4482+
std::vector<DominatorTree::UpdateType> Updates;
4483+
44824484
SmallVector<BasicBlock *, 8> Preds(pred_begin(BB), pred_end(BB));
44834485
for (unsigned i = 0, e = Preds.size(); i != e; ++i) {
4484-
Instruction *TI = Preds[i]->getTerminator();
4486+
auto *Predecessor = Preds[i];
4487+
Instruction *TI = Predecessor->getTerminator();
44854488
IRBuilder<> Builder(TI);
44864489
if (auto *BI = dyn_cast<BranchInst>(TI)) {
44874490
if (BI->isUnconditional()) {
@@ -4491,6 +4494,9 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
44914494
Changed = true;
44924495
} else {
44934496
Value* Cond = BI->getCondition();
4497+
assert(BI->getSuccessor(0) != BI->getSuccessor(1) &&
4498+
"Same-destination conditional branch instruction was "
4499+
"already canonicalized into an unconditional branch.");
44944500
if (BI->getSuccessor(0) == BB) {
44954501
Builder.CreateAssumption(Builder.CreateNot(Cond));
44964502
Builder.CreateBr(BI->getSuccessor(1));
@@ -4502,6 +4508,7 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
45024508
EraseTerminatorAndDCECond(BI);
45034509
Changed = true;
45044510
}
4511+
Updates.push_back({DominatorTree::Delete, Predecessor, BB});
45054512
} else if (auto *SI = dyn_cast<SwitchInst>(TI)) {
45064513
SwitchInstProfUpdateWrapper SU(*SI);
45074514
for (auto i = SU->case_begin(), e = SU->case_end(); i != e;) {
@@ -4514,14 +4521,21 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
45144521
e = SU->case_end();
45154522
Changed = true;
45164523
}
4524+
Updates.push_back({DominatorTree::Delete, Predecessor, BB});
45174525
} else if (auto *II = dyn_cast<InvokeInst>(TI)) {
45184526
if (II->getUnwindDest() == BB) {
4519-
removeUnwindEdge(TI->getParent());
4527+
if (DTU)
4528+
DTU->applyUpdatesPermissive(Updates);
4529+
Updates.clear();
4530+
removeUnwindEdge(TI->getParent(), DTU);
45204531
Changed = true;
45214532
}
45224533
} else if (auto *CSI = dyn_cast<CatchSwitchInst>(TI)) {
45234534
if (CSI->getUnwindDest() == BB) {
4524-
removeUnwindEdge(TI->getParent());
4535+
if (DTU)
4536+
DTU->applyUpdatesPermissive(Updates);
4537+
Updates.clear();
4538+
removeUnwindEdge(TI->getParent(), DTU);
45254539
Changed = true;
45264540
continue;
45274541
}
@@ -4536,35 +4550,54 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
45364550
Changed = true;
45374551
}
45384552
}
4553+
Updates.push_back({DominatorTree::Delete, Predecessor, BB});
45394554
if (CSI->getNumHandlers() == 0) {
4540-
BasicBlock *CatchSwitchBB = CSI->getParent();
45414555
if (CSI->hasUnwindDest()) {
4542-
// Redirect preds to the unwind dest
4543-
CatchSwitchBB->replaceAllUsesWith(CSI->getUnwindDest());
4556+
// Redirect all predecessors of the block containing CatchSwitchInst
4557+
// to instead branch to the CatchSwitchInst's unwind destination.
4558+
for (auto *PredecessorOfPredecessor : predecessors(Predecessor)) {
4559+
Updates.push_back(
4560+
{DominatorTree::Delete, PredecessorOfPredecessor, Predecessor});
4561+
Updates.push_back({DominatorTree::Insert, PredecessorOfPredecessor,
4562+
CSI->getUnwindDest()});
4563+
}
4564+
Predecessor->replaceAllUsesWith(CSI->getUnwindDest());
45444565
} else {
45454566
// Rewrite all preds to unwind to caller (or from invoke to call).
4546-
SmallVector<BasicBlock *, 8> EHPreds(predecessors(CatchSwitchBB));
4567+
if (DTU)
4568+
DTU->applyUpdatesPermissive(Updates);
4569+
Updates.clear();
4570+
SmallVector<BasicBlock *, 8> EHPreds(predecessors(Predecessor));
45474571
for (BasicBlock *EHPred : EHPreds)
4548-
removeUnwindEdge(EHPred);
4572+
removeUnwindEdge(EHPred, DTU);
45494573
}
45504574
// The catchswitch is no longer reachable.
45514575
new UnreachableInst(CSI->getContext(), CSI);
45524576
CSI->eraseFromParent();
45534577
Changed = true;
45544578
}
4555-
} else if (isa<CleanupReturnInst>(TI)) {
4579+
} else if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) {
4580+
assert(CRI->hasUnwindDest() && CRI->getUnwindDest() == BB &&
4581+
"Expected to always have an unwind to BB.");
4582+
Updates.push_back({DominatorTree::Delete, Predecessor, BB});
45564583
new UnreachableInst(TI->getContext(), TI);
45574584
TI->eraseFromParent();
45584585
Changed = true;
45594586
}
45604587
}
45614588

4589+
if (DTU)
4590+
DTU->applyUpdatesPermissive(Updates);
4591+
45624592
// If this block is now dead, remove it.
45634593
if (pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()) {
45644594
// We know there are no successors, so just nuke the block.
45654595
if (LoopHeaders)
45664596
LoopHeaders->erase(BB);
4567-
BB->eraseFromParent();
4597+
if (DTU)
4598+
DTU->deleteBB(BB);
4599+
else
4600+
BB->eraseFromParent();
45684601
return true;
45694602
}
45704603

llvm/test/Transforms/CallSiteSplitting/split-loop.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt -S -callsite-splitting -simplifycfg < %s | FileCheck %s
2+
; RUN: opt -S -callsite-splitting -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
33

44
define i16 @test1() {
55
; CHECK-LABEL: @test1(

llvm/test/Transforms/LoopDeletion/2008-05-06-Phi.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt < %s -inline -instcombine -jump-threading -licm -simple-loop-unswitch -instcombine -indvars -loop-deletion -gvn -simplifycfg -verify -disable-output
1+
; RUN: opt < %s -inline -instcombine -jump-threading -licm -simple-loop-unswitch -instcombine -indvars -loop-deletion -gvn -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -verify -disable-output
22

33
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
44
target triple = "i386-apple-darwin9"
@@ -18,7 +18,7 @@ target triple = "i386-apple-darwin9"
1818
@scaleFactorsPH = external global [2 x [2 x %struct.BF_PartHolder*]] ; <[2 x [2 x %struct.BF_PartHolder*]]*> [#uses=1]
1919
@slen1_tab = external constant [16 x i32] ; <[16 x i32]*> [#uses=1]
2020

21-
declare %struct.BF_PartHolder* @BF_addElement(%struct.BF_PartHolder*, %struct.BF_BitstreamElement*) nounwind
21+
declare %struct.BF_PartHolder* @BF_addElement(%struct.BF_PartHolder*, %struct.BF_BitstreamElement*) nounwind
2222

2323
define %struct.BF_PartHolder* @BF_addEntry(%struct.BF_PartHolder* %thePH, i32 %value, i32 %length) nounwind {
2424
entry:
@@ -38,7 +38,7 @@ bb13: ; preds = %entry
3838

3939
define void @III_format_bitstream(%struct.lame_global_flags* %gfp, i32 %bitsPerFrame, [2 x [576 x i32]]* %l3_enc, %struct.III_side_info_t* %l3_side, [2 x %struct.III_scalefac_t]* %scalefac, %struct.Bit_stream_struc* %in_bs) nounwind {
4040
entry:
41-
call fastcc void @encodeMainData( %struct.lame_global_flags* %gfp, [2 x [576 x i32]]* %l3_enc, %struct.III_side_info_t* %l3_side, [2 x %struct.III_scalefac_t]* %scalefac ) nounwind
41+
call fastcc void @encodeMainData( %struct.lame_global_flags* %gfp, [2 x [576 x i32]]* %l3_enc, %struct.III_side_info_t* %l3_side, [2 x %struct.III_scalefac_t]* %scalefac ) nounwind
4242
unreachable
4343
}
4444

llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt < %s -simplifycfg -S | FileCheck %s
2+
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
33

44
define void @test1(i1 %C, i1* %BP) {
55
; CHECK-LABEL: @test1(

llvm/test/Transforms/SimplifyCFG/X86/PR30210.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt -S -simplifycfg < %s | FileCheck %s
2+
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
33
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
44
target triple = "x86_64-unknown-linux-gnu"
55

llvm/test/Transforms/SimplifyCFG/branch-fold.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt < %s -simplifycfg -S | FileCheck %s
1+
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
22

33
define void @test(i32* %P, i32* %Q, i1 %A, i1 %B) {
44
; CHECK: test

llvm/test/Transforms/SimplifyCFG/empty-catchpad.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt < %s -simplifycfg -S | FileCheck %s
1+
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
22

33
declare void @f()
44
declare void @llvm.foo(i32) nounwind

llvm/test/Transforms/SimplifyCFG/invoke_unwind_lifetime.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt < %s -simplifycfg -S | FileCheck %s
2+
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
33

44
declare void @llvm.lifetime.start.p0i8(i64, i8*)
55
declare void @llvm.lifetime.end.p0i8(i64, i8*)

llvm/test/Transforms/SimplifyCFG/switch-profmd.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt -S -simplifycfg < %s | FileCheck %s
1+
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
22

33
declare i32 @f(i32 %val)
44

llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt %s -simplifycfg -S | FileCheck %s
2+
; RUN: opt %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
33

44
declare i32 @f(i32)
55

llvm/test/Transforms/SimplifyCFG/unreachable_assume.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2-
; RUN: opt %s -simplifycfg -instcombine -S | FileCheck %s
2+
; RUN: opt %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -instcombine -S | FileCheck %s
33

44
define i32 @assume1(i32 %p) {
55
; CHECK-LABEL: @assume1(

llvm/test/Transforms/SimplifyCFG/wineh-unreachable.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: opt -S -simplifycfg < %s | FileCheck %s
1+
; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
22

33
declare void @Personality()
44
declare void @f()

0 commit comments

Comments
 (0)