Add a helper to remove a branch and DCE the condition, and use it
authorEli Friedman <eli.friedman@gmail.com>
Tue, 16 Dec 2008 20:54:32 +0000 (20:54 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Tue, 16 Dec 2008 20:54:32 +0000 (20:54 +0000)
consistently for deleting branches.  In addition to being slightly
more readable, this makes SimplifyCFG a bit better
about cleaning up after itself when it makes conditions unused.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61100 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Utils/SimplifyCFG.cpp
test/Transforms/SimplifyCFG/2008-12-16-DCECond.ll [new file with mode: 0644]

index e7bd75e04931084b43f8e1400d76f2d2b5db4813..366021e6480ef8c673558264867b25c9315f45df 100644 (file)
@@ -386,6 +386,7 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB,
         // We can hoist loads that are non-volatile and obviously cannot trap.
         if (cast<LoadInst>(I)->isVolatile())
           return false;
+        // FIXME: A computation of a constant can trap!
         if (!isa<AllocaInst>(I->getOperand(0)) &&
             !isa<Constant>(I->getOperand(0)))
           return false;
@@ -494,6 +495,19 @@ static bool GatherValueComparisons(Instruction *Cond, Value *&CompVal,
   return false;
 }
 
+static void EraseTerminatorInstAndDCECond(TerminatorInst *TI) {
+  Instruction* Cond = 0;
+  if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
+    Cond = dyn_cast<Instruction>(SI->getCondition());
+  } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
+    if (BI->isConditional())
+      Cond = dyn_cast<Instruction>(BI->getCondition());
+  }
+
+  TI->eraseFromParent();
+  if (Cond) RecursivelyDeleteTriviallyDeadInstructions(Cond);
+}
+
 /// isValueEqualityComparison - Return true if the specified terminator checks
 /// to see if a value is equal to constant integer value.
 static Value *isValueEqualityComparison(TerminatorInst *TI) {
@@ -617,11 +631,10 @@ static bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
     // PredCases.  If there are any cases in ThisCases that are in PredCases, we
     // can simplify TI.
     if (ValuesOverlap(PredCases, ThisCases)) {
-      if (BranchInst *BTI = dyn_cast<BranchInst>(TI)) {
+      if (isa<BranchInst>(TI)) {
         // Okay, one of the successors of this condbr is dead.  Convert it to a
         // uncond br.
         assert(ThisCases.size() == 1 && "Branch can only have one case!");
-        Value *Cond = BTI->getCondition();
         // Insert the new branch.
         Instruction *NI = BranchInst::Create(ThisDef, TI);
 
@@ -631,10 +644,7 @@ static bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
         DOUT << "Threading pred instr: " << *Pred->getTerminator()
              << "Through successor TI: " << *TI << "Leaving: " << *NI << "\n";
 
-        TI->eraseFromParent();   // Nuke the old one.
-        // If condition is now dead, nuke it.
-        if (Instruction *CondI = dyn_cast<Instruction>(Cond))
-          RecursivelyDeleteTriviallyDeadInstructions(CondI);
+        EraseTerminatorInstAndDCECond(TI);
         return true;
 
       } else {
@@ -697,12 +707,8 @@ static bool SimplifyEqualityComparisonWithOnlyPredecessor(TerminatorInst *TI,
 
     DOUT << "Threading pred instr: " << *Pred->getTerminator()
          << "Through successor TI: " << *TI << "Leaving: " << *NI << "\n";
-    Instruction *Cond = 0;
-    if (BranchInst *BI = dyn_cast<BranchInst>(TI))
-      Cond = dyn_cast<Instruction>(BI->getCondition());
-    TI->eraseFromParent();   // Nuke the old one.
 
-    if (Cond) RecursivelyDeleteTriviallyDeadInstructions(Cond);
+    EraseTerminatorInstAndDCECond(TI);
     return true;
   }
   return false;
@@ -811,14 +817,7 @@ static bool FoldValueComparisonIntoPredecessors(TerminatorInst *TI) {
       for (unsigned i = 0, e = PredCases.size(); i != e; ++i)
         NewSI->addCase(PredCases[i].first, PredCases[i].second);
 
-      Instruction *DeadCond = 0;
-      if (BranchInst *BI = dyn_cast<BranchInst>(PTI))
-        // If PTI is a branch, remember the condition.
-        DeadCond = dyn_cast<Instruction>(BI->getCondition());
-      Pred->getInstList().erase(PTI);
-
-      // If the condition is dead now, remove the instruction tree.
-      if (DeadCond) RecursivelyDeleteTriviallyDeadInstructions(DeadCond);
+      EraseTerminatorInstAndDCECond(PTI);
 
       // Okay, last check.  If BB is still a successor of PSI, then we must
       // have an infinite loop case.  If so, add an infinitely looping block
@@ -921,7 +920,7 @@ HoistTerminator:
   for (succ_iterator SI = succ_begin(BB1), E = succ_end(BB1); SI != E; ++SI)
     AddPredecessorToBlock(*SI, BIParent, BB1);
 
-  BI->eraseFromParent();
+  EraseTerminatorInstAndDCECond(BI);
   return true;
 }
 
@@ -1331,7 +1330,7 @@ static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) {
     TrueSucc->removePredecessor(BI->getParent());
     FalseSucc->removePredecessor(BI->getParent());
     ReturnInst::Create(0, BI);
-    BI->eraseFromParent();
+    EraseTerminatorInstAndDCECond(BI);
     return true;
   }
     
@@ -1386,10 +1385,8 @@ static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) {
        << "\n  " << *BI << "NewRet = " << *RI
        << "TRUEBLOCK: " << *TrueSucc << "FALSEBLOCK: "<< *FalseSucc;
       
-  BI->eraseFromParent();
-  
-  if (Instruction *BrCondI = dyn_cast<Instruction>(BrCond))
-    RecursivelyDeleteTriviallyDeadInstructions(BrCondI);
+  EraseTerminatorInstAndDCECond(BI);
+
   return true;
 }
 
@@ -1910,10 +1907,10 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
           } else {
             if (BI->getSuccessor(0) == BB) {
               BranchInst::Create(BI->getSuccessor(1), BI);
-              BI->eraseFromParent();
+              EraseTerminatorInstAndDCECond(BI);
             } else if (BI->getSuccessor(1) == BB) {
               BranchInst::Create(BI->getSuccessor(0), BI);
-              BI->eraseFromParent();
+              EraseTerminatorInstAndDCECond(BI);
               Changed = true;
             }
           }
@@ -2086,11 +2083,7 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
           }
 
           // Erase the old branch instruction.
-          (*PI)->getInstList().erase(BI);
-
-          // Erase the potentially condition tree that was used to computed the
-          // branch condition.
-          RecursivelyDeleteTriviallyDeadInstructions(Cond);
+          EraseTerminatorInstAndDCECond(BI);
           return true;
         }
       }
diff --git a/test/Transforms/SimplifyCFG/2008-12-16-DCECond.ll b/test/Transforms/SimplifyCFG/2008-12-16-DCECond.ll
new file mode 100644 (file)
index 0000000..b52d10d
--- /dev/null
@@ -0,0 +1,46 @@
+; RUN: llvm-as < %s | opt -simplifycfg | llvm-dis | not grep icmp
+; ModuleID = '/tmp/x.bc'
+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 = "i686-pc-linux-gnu"
+
+define i32 @x(i32 %x) {
+entry:
+       %cmp = icmp eq i32 %x, 8                ; <i1> [#uses=1]
+       br i1 %cmp, label %ifthen, label %ifend
+
+ifthen:                ; preds = %entry
+       %call = call i32 (...)* @foo()          ; <i32> [#uses=0]
+       br label %ifend
+
+ifend:         ; preds = %ifthen, %entry
+       %cmp2 = icmp ne i32 %x, 8               ; <i1> [#uses=1]
+       br i1 %cmp2, label %ifthen3, label %ifend5
+
+ifthen3:               ; preds = %ifend
+       %call4 = call i32 (...)* @foo()         ; <i32> [#uses=0]
+       br label %ifend5
+
+ifend5:                ; preds = %ifthen3, %ifend
+       %cmp7 = icmp eq i32 %x, 9               ; <i1> [#uses=1]
+       br i1 %cmp7, label %ifthen8, label %ifend10
+
+ifthen8:               ; preds = %ifend5
+       %call9 = call i32 (...)* @bar()         ; <i32> [#uses=0]
+       br label %ifend10
+
+ifend10:               ; preds = %ifthen8, %ifend5
+       %cmp12 = icmp ne i32 %x, 9              ; <i1> [#uses=1]
+       br i1 %cmp12, label %ifthen13, label %ifend15
+
+ifthen13:              ; preds = %ifend10
+       %call14 = call i32 (...)* @bar()                ; <i32> [#uses=0]
+       br label %ifend15
+
+ifend15:               ; preds = %ifthen13, %ifend10
+       ret i32 0
+}
+
+declare i32 @foo(...)
+
+declare i32 @bar(...)
+