Avoid making a broken transformation!
authorChris Lattner <sabre@nondot.org>
Sat, 3 Nov 2001 21:30:22 +0000 (21:30 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 3 Nov 2001 21:30:22 +0000 (21:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1115 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/DCE.cpp

index ac3ae7b66baf32e8920c2a96bfce2c62e5c1f9c9..16d953401889ca581ceeca84f15a3e1a12cc3ca0 100644 (file)
@@ -105,11 +105,13 @@ static void ReplaceUsesWithConstant(Instruction *I) {
 // PropogatePredecessors - This gets "Succ" ready to have the predecessors from
 // "BB".  This is a little tricky because "Succ" has PHI nodes, which need to
 // have extra slots added to them to hold the merge edges from BB's
-// predecessors.
+// predecessors.  This function returns true (failure) if the Succ BB already
+// has a predecessor that is a predecessor of BB.
 //
-// Assumption: BB is the single predecessor of Succ.
+// Assumption: Succ is the single successor for BB.
 //
-static void PropogatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) {
+static bool PropogatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) {
+  assert(*BB->succ_begin() == Succ && "Succ is not successor of BB!");
   assert(isa<PHINode>(Succ->front()) && "Only works on PHId BBs!");
 
   // If there is more than one predecessor, and there are PHI nodes in
@@ -117,6 +119,15 @@ static void PropogatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) {
   //
   const vector<BasicBlock*> BBPreds(BB->pred_begin(), BB->pred_end());
 
+  // Check to see if one of the predecessors of BB is already a predecessor of
+  // Succ.  If so, we cannot do the transformation!
+  //
+  for (BasicBlock::pred_iterator PI = Succ->pred_begin(), PE = Succ->pred_end();
+         PI != PE; ++PI) {
+    if (find(BBPreds.begin(), BBPreds.end(), *PI) != BBPreds.end())
+      return true;
+  }
+
   BasicBlock::iterator I = Succ->begin();
   do {                     // Loop over all of the PHI nodes in the successor BB
     PHINode *PN = cast<PHINode>(*I);
@@ -131,6 +142,7 @@ static void PropogatePredecessorsForPHIs(BasicBlock *BB, BasicBlock *Succ) {
 
     ++I;
   } while (isa<PHINode>(*I));
+  return false;
 }
 
 
@@ -182,28 +194,29 @@ bool opt::SimplifyCFG(Method::iterator &BBIt) {
   // successor.  If so, replace block references with successor.
   BasicBlock::succ_iterator SI(BB->succ_begin());
   if (SI != BB->succ_end() && ++SI == BB->succ_end()) {  // One succ?
-    Instruction *I = BB->front();
-    if (I->isTerminator()) {   // Terminator is the only instruction!
+    if (BB->front()->isTerminator()) {   // Terminator is the only instruction!
       BasicBlock *Succ = *BB->succ_begin(); // There is exactly one successor
       //cerr << "Killing Trivial BB: \n" << BB;
       
       if (Succ != BB) {   // Arg, don't hurt infinite loops!
-       if (isa<PHINode>(Succ->front())) {
-         // If our successor has PHI nodes, then we need to update them to
-         // include entries for BB's predecessors, not for BB itself.
-         //
-         PropogatePredecessorsForPHIs(BB, Succ);
-       }
-       
-       BB->replaceAllUsesWith(Succ);
-       BB = M->getBasicBlocks().remove(BBIt);
+        // If our successor has PHI nodes, then we need to update them to
+        // include entries for BB's predecessors, not for BB itself.
+        // Be careful though, if this transformation fails (returns true) then
+        // we cannot do this transformation!
+        //
+       if (!isa<PHINode>(Succ->front()) ||
+            !PropogatePredecessorsForPHIs(BB, Succ)) {
+          
+          BB->replaceAllUsesWith(Succ);
+          BB = M->getBasicBlocks().remove(BBIt);
        
-       if (BB->hasName() && !Succ->hasName())  // Transfer name if we can
-         Succ->setName(BB->getName());
-       delete BB;                              // Delete basic block
-       
-       //cerr << "Method after removal: \n" << M;
-       return true;
+          if (BB->hasName() && !Succ->hasName())  // Transfer name if we can
+            Succ->setName(BB->getName());
+          delete BB;                              // Delete basic block
+          
+          //cerr << "Method after removal: \n" << M;
+          return true;
+       }
       }
     }
   }