[llvm-branch-commits] [llvm] 2d07414 - [SimplifyCFG] Teach simplifyUnreachable() to preserve DomTree

Roman Lebedev via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Dec 17 13:43:47 PST 2020


Author: Roman Lebedev
Date: 2020-12-18T00:37:22+03:00
New Revision: 2d07414ee5f74a09fb89723b4a9bb0818bdc2e18

URL: https://github.com/llvm/llvm-project/commit/2d07414ee5f74a09fb89723b4a9bb0818bdc2e18
DIFF: https://github.com/llvm/llvm-project/commit/2d07414ee5f74a09fb89723b4a9bb0818bdc2e18.diff

LOG: [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.

Added: 
    

Modified: 
    llvm/lib/Transforms/Utils/SimplifyCFG.cpp
    llvm/test/Transforms/CallSiteSplitting/split-loop.ll
    llvm/test/Transforms/LoopDeletion/2008-05-06-Phi.ll
    llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
    llvm/test/Transforms/SimplifyCFG/X86/PR30210.ll
    llvm/test/Transforms/SimplifyCFG/branch-fold.ll
    llvm/test/Transforms/SimplifyCFG/empty-catchpad.ll
    llvm/test/Transforms/SimplifyCFG/invoke_unwind_lifetime.ll
    llvm/test/Transforms/SimplifyCFG/switch-profmd.ll
    llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll
    llvm/test/Transforms/SimplifyCFG/unreachable_assume.ll
    llvm/test/Transforms/SimplifyCFG/wineh-unreachable.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 9e4650fefff7..6a0859d84c89 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -4479,9 +4479,12 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
   if (&BB->front() != UI)
     return Changed;
 
+  std::vector<DominatorTree::UpdateType> Updates;
+
   SmallVector<BasicBlock *, 8> Preds(pred_begin(BB), pred_end(BB));
   for (unsigned i = 0, e = Preds.size(); i != e; ++i) {
-    Instruction *TI = Preds[i]->getTerminator();
+    auto *Predecessor = Preds[i];
+    Instruction *TI = Predecessor->getTerminator();
     IRBuilder<> Builder(TI);
     if (auto *BI = dyn_cast<BranchInst>(TI)) {
       if (BI->isUnconditional()) {
@@ -4491,6 +4494,9 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
         Changed = true;
       } else {
         Value* Cond = BI->getCondition();
+        assert(BI->getSuccessor(0) != BI->getSuccessor(1) &&
+               "Same-destination conditional branch instruction was "
+               "already canonicalized into an unconditional branch.");
         if (BI->getSuccessor(0) == BB) {
           Builder.CreateAssumption(Builder.CreateNot(Cond));
           Builder.CreateBr(BI->getSuccessor(1));
@@ -4502,6 +4508,7 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
         EraseTerminatorAndDCECond(BI);
         Changed = true;
       }
+      Updates.push_back({DominatorTree::Delete, Predecessor, BB});
     } else if (auto *SI = dyn_cast<SwitchInst>(TI)) {
       SwitchInstProfUpdateWrapper SU(*SI);
       for (auto i = SU->case_begin(), e = SU->case_end(); i != e;) {
@@ -4514,14 +4521,21 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
         e = SU->case_end();
         Changed = true;
       }
+      Updates.push_back({DominatorTree::Delete, Predecessor, BB});
     } else if (auto *II = dyn_cast<InvokeInst>(TI)) {
       if (II->getUnwindDest() == BB) {
-        removeUnwindEdge(TI->getParent());
+        if (DTU)
+          DTU->applyUpdatesPermissive(Updates);
+        Updates.clear();
+        removeUnwindEdge(TI->getParent(), DTU);
         Changed = true;
       }
     } else if (auto *CSI = dyn_cast<CatchSwitchInst>(TI)) {
       if (CSI->getUnwindDest() == BB) {
-        removeUnwindEdge(TI->getParent());
+        if (DTU)
+          DTU->applyUpdatesPermissive(Updates);
+        Updates.clear();
+        removeUnwindEdge(TI->getParent(), DTU);
         Changed = true;
         continue;
       }
@@ -4536,35 +4550,54 @@ bool SimplifyCFGOpt::simplifyUnreachable(UnreachableInst *UI) {
           Changed = true;
         }
       }
+      Updates.push_back({DominatorTree::Delete, Predecessor, BB});
       if (CSI->getNumHandlers() == 0) {
-        BasicBlock *CatchSwitchBB = CSI->getParent();
         if (CSI->hasUnwindDest()) {
-          // Redirect preds to the unwind dest
-          CatchSwitchBB->replaceAllUsesWith(CSI->getUnwindDest());
+          // Redirect all predecessors of the block containing CatchSwitchInst
+          // to instead branch to the CatchSwitchInst's unwind destination.
+          for (auto *PredecessorOfPredecessor : predecessors(Predecessor)) {
+            Updates.push_back(
+                {DominatorTree::Delete, PredecessorOfPredecessor, Predecessor});
+            Updates.push_back({DominatorTree::Insert, PredecessorOfPredecessor,
+                               CSI->getUnwindDest()});
+          }
+          Predecessor->replaceAllUsesWith(CSI->getUnwindDest());
         } else {
           // Rewrite all preds to unwind to caller (or from invoke to call).
-          SmallVector<BasicBlock *, 8> EHPreds(predecessors(CatchSwitchBB));
+          if (DTU)
+            DTU->applyUpdatesPermissive(Updates);
+          Updates.clear();
+          SmallVector<BasicBlock *, 8> EHPreds(predecessors(Predecessor));
           for (BasicBlock *EHPred : EHPreds)
-            removeUnwindEdge(EHPred);
+            removeUnwindEdge(EHPred, DTU);
         }
         // The catchswitch is no longer reachable.
         new UnreachableInst(CSI->getContext(), CSI);
         CSI->eraseFromParent();
         Changed = true;
       }
-    } else if (isa<CleanupReturnInst>(TI)) {
+    } else if (auto *CRI = dyn_cast<CleanupReturnInst>(TI)) {
+      assert(CRI->hasUnwindDest() && CRI->getUnwindDest() == BB &&
+             "Expected to always have an unwind to BB.");
+      Updates.push_back({DominatorTree::Delete, Predecessor, BB});
       new UnreachableInst(TI->getContext(), TI);
       TI->eraseFromParent();
       Changed = true;
     }
   }
 
+  if (DTU)
+    DTU->applyUpdatesPermissive(Updates);
+
   // If this block is now dead, remove it.
   if (pred_empty(BB) && BB != &BB->getParent()->getEntryBlock()) {
     // We know there are no successors, so just nuke the block.
     if (LoopHeaders)
       LoopHeaders->erase(BB);
-    BB->eraseFromParent();
+    if (DTU)
+      DTU->deleteBB(BB);
+    else
+      BB->eraseFromParent();
     return true;
   }
 

diff  --git a/llvm/test/Transforms/CallSiteSplitting/split-loop.ll b/llvm/test/Transforms/CallSiteSplitting/split-loop.ll
index 1e71643b7b9e..0c65e724c8a7 100644
--- a/llvm/test/Transforms/CallSiteSplitting/split-loop.ll
+++ b/llvm/test/Transforms/CallSiteSplitting/split-loop.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -callsite-splitting -simplifycfg < %s | FileCheck %s
+; RUN: opt -S -callsite-splitting -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
 
 define i16 @test1() {
 ; CHECK-LABEL: @test1(

diff  --git a/llvm/test/Transforms/LoopDeletion/2008-05-06-Phi.ll b/llvm/test/Transforms/LoopDeletion/2008-05-06-Phi.ll
index f5f7970566cb..79170e6615b7 100644
--- a/llvm/test/Transforms/LoopDeletion/2008-05-06-Phi.ll
+++ b/llvm/test/Transforms/LoopDeletion/2008-05-06-Phi.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -inline -instcombine -jump-threading -licm -simple-loop-unswitch -instcombine -indvars -loop-deletion -gvn -simplifycfg -verify -disable-output
+; 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
 
 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"
 target triple = "i386-apple-darwin9"
@@ -18,7 +18,7 @@ target triple = "i386-apple-darwin9"
 @scaleFactorsPH = external global [2 x [2 x %struct.BF_PartHolder*]]		; <[2 x [2 x %struct.BF_PartHolder*]]*> [#uses=1]
 @slen1_tab = external constant [16 x i32]		; <[16 x i32]*> [#uses=1]
 
-declare %struct.BF_PartHolder* @BF_addElement(%struct.BF_PartHolder*, %struct.BF_BitstreamElement*) nounwind 
+declare %struct.BF_PartHolder* @BF_addElement(%struct.BF_PartHolder*, %struct.BF_BitstreamElement*) nounwind
 
 define %struct.BF_PartHolder* @BF_addEntry(%struct.BF_PartHolder* %thePH, i32 %value, i32 %length) nounwind  {
 entry:
@@ -38,7 +38,7 @@ bb13:		; preds = %entry
 
 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  {
 entry:
-	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 
+	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
 	unreachable
 }
 

diff  --git a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
index c8f59d4bd9ae..4ec8fe7e68f8 100644
--- a/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
+++ b/llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -simplifycfg -S | FileCheck %s
+; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
 
 define void @test1(i1 %C, i1* %BP) {
 ; CHECK-LABEL: @test1(

diff  --git a/llvm/test/Transforms/SimplifyCFG/X86/PR30210.ll b/llvm/test/Transforms/SimplifyCFG/X86/PR30210.ll
index bc422ddcd5f6..8704bcf005ea 100644
--- a/llvm/test/Transforms/SimplifyCFG/X86/PR30210.ll
+++ b/llvm/test/Transforms/SimplifyCFG/X86/PR30210.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -simplifycfg < %s | FileCheck %s
+; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
 target triple = "x86_64-unknown-linux-gnu"
 

diff  --git a/llvm/test/Transforms/SimplifyCFG/branch-fold.ll b/llvm/test/Transforms/SimplifyCFG/branch-fold.ll
index 7097dea424e1..a4ac23bada70 100644
--- a/llvm/test/Transforms/SimplifyCFG/branch-fold.ll
+++ b/llvm/test/Transforms/SimplifyCFG/branch-fold.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -simplifycfg -S | FileCheck %s
+; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
 
 define void @test(i32* %P, i32* %Q, i1 %A, i1 %B) {
 ; CHECK: test

diff  --git a/llvm/test/Transforms/SimplifyCFG/empty-catchpad.ll b/llvm/test/Transforms/SimplifyCFG/empty-catchpad.ll
index 2926cd3f7dc7..6e9141568df6 100644
--- a/llvm/test/Transforms/SimplifyCFG/empty-catchpad.ll
+++ b/llvm/test/Transforms/SimplifyCFG/empty-catchpad.ll
@@ -1,4 +1,4 @@
-; RUN: opt < %s -simplifycfg -S | FileCheck %s
+; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
 
 declare void @f()
 declare void @llvm.foo(i32) nounwind

diff  --git a/llvm/test/Transforms/SimplifyCFG/invoke_unwind_lifetime.ll b/llvm/test/Transforms/SimplifyCFG/invoke_unwind_lifetime.ll
index a498976c10f8..c758826dc435 100644
--- a/llvm/test/Transforms/SimplifyCFG/invoke_unwind_lifetime.ll
+++ b/llvm/test/Transforms/SimplifyCFG/invoke_unwind_lifetime.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt < %s -simplifycfg -S | FileCheck %s
+; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
 
 declare void @llvm.lifetime.start.p0i8(i64, i8*)
 declare void @llvm.lifetime.end.p0i8(i64, i8*)

diff  --git a/llvm/test/Transforms/SimplifyCFG/switch-profmd.ll b/llvm/test/Transforms/SimplifyCFG/switch-profmd.ll
index c17214e18f20..3f8f5716604a 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch-profmd.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch-profmd.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -simplifycfg < %s | FileCheck %s
+; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
 
 declare i32 @f(i32 %val)
 

diff  --git a/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll b/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll
index d99e84b6b940..7125575b2f33 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %s -simplifycfg -S | FileCheck %s
+; RUN: opt %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
 
 declare i32 @f(i32)
 

diff  --git a/llvm/test/Transforms/SimplifyCFG/unreachable_assume.ll b/llvm/test/Transforms/SimplifyCFG/unreachable_assume.ll
index e0d1e27a9952..2eb7f4da1d8a 100644
--- a/llvm/test/Transforms/SimplifyCFG/unreachable_assume.ll
+++ b/llvm/test/Transforms/SimplifyCFG/unreachable_assume.ll
@@ -1,5 +1,5 @@
 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt %s -simplifycfg -instcombine -S | FileCheck %s
+; RUN: opt %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -instcombine -S | FileCheck %s
 
 define i32 @assume1(i32 %p) {
 ; CHECK-LABEL: @assume1(

diff  --git a/llvm/test/Transforms/SimplifyCFG/wineh-unreachable.ll b/llvm/test/Transforms/SimplifyCFG/wineh-unreachable.ll
index 7655fa7875f2..c951294233ff 100644
--- a/llvm/test/Transforms/SimplifyCFG/wineh-unreachable.ll
+++ b/llvm/test/Transforms/SimplifyCFG/wineh-unreachable.ll
@@ -1,4 +1,4 @@
-; RUN: opt -S -simplifycfg < %s | FileCheck %s
+; RUN: opt -S -simplifycfg -simplifycfg-require-and-preserve-domtree=1 < %s | FileCheck %s
 
 declare void @Personality()
 declare void @f()


        


More information about the llvm-branch-commits mailing list