[llvm-commits] CVS: llvm/lib/Transforms/Utils/CloneFunction.cpp

Chris Lattner lattner at cs.uiuc.edu
Thu Jun 1 12:19:36 PDT 2006



Changes in directory llvm/lib/Transforms/Utils:

CloneFunction.cpp updated: 1.28 -> 1.29
---
Log message:

Make the "pruning cloner" smarter.  As it propagates constants through the
code (while cloning) it often gets the branch/switch instructions.  Since it
knows that edges of the CFG are dead, it need not clone (or even look) at
the obviously dead blocks.  This should speed up the inliner substantially on
code where there are lots of inlinable calls to functions with constant 
arguments.  On C++ code in particular, this kicks in.



---
Diffs of the changes:  (+146 -23)

 CloneFunction.cpp |  169 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 146 insertions(+), 23 deletions(-)


Index: llvm/lib/Transforms/Utils/CloneFunction.cpp
diff -u llvm/lib/Transforms/Utils/CloneFunction.cpp:1.28 llvm/lib/Transforms/Utils/CloneFunction.cpp:1.29
--- llvm/lib/Transforms/Utils/CloneFunction.cpp:1.28	Sat May 27 12:28:13 2006
+++ llvm/lib/Transforms/Utils/CloneFunction.cpp	Thu Jun  1 14:19:23 2006
@@ -18,6 +18,7 @@
 #include "llvm/DerivedTypes.h"
 #include "llvm/Instructions.h"
 #include "llvm/Function.h"
+#include "llvm/Support/CFG.h"
 #include "ValueMapper.h"
 #include "llvm/Transforms/Utils/Local.h"
 using namespace llvm;
@@ -195,7 +196,7 @@
   
   // Loop over all instructions, and copy them over, DCE'ing as we go.  This
   // loop doesn't include the terminator.
-  for (BasicBlock::const_iterator II = BB->begin(), IE = BB->end();
+  for (BasicBlock::const_iterator II = BB->begin(), IE = --BB->end();
        II != IE; ++II) {
     // If this instruction constant folds, don't bother cloning the instruction,
     // instead, just add the constant to the value map.
@@ -219,9 +220,51 @@
     }
   }
   
+  // Finally, clone over the terminator.
+  const TerminatorInst *OldTI = BB->getTerminator();
+  bool TerminatorDone = false;
+  if (const BranchInst *BI = dyn_cast<BranchInst>(OldTI)) {
+    if (BI->isConditional()) {
+      // If the condition was a known constant in the callee...
+      ConstantBool *Cond = dyn_cast<ConstantBool>(BI->getCondition());
+      if (Cond == 0)  // Or is a known constant in the caller...
+        Cond = dyn_cast_or_null<ConstantBool>(ValueMap[BI->getCondition()]);
+      if (Cond) {     // Constant fold to uncond branch!
+        BasicBlock *Dest = BI->getSuccessor(!Cond->getValue());
+        ValueMap[OldTI] = new BranchInst(Dest, NewBB);
+        CloneBlock(Dest);
+        TerminatorDone = true;
+      }
+    }
+  } else if (const SwitchInst *SI = dyn_cast<SwitchInst>(OldTI)) {
+    // If switching on a value known constant in the caller.
+    ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition());
+    if (Cond == 0)  // Or known constant after constant prop in the callee...
+      Cond = dyn_cast_or_null<ConstantInt>(ValueMap[SI->getCondition()]);
+    if (Cond) {     // Constant fold to uncond branch!
+      BasicBlock *Dest = SI->getSuccessor(SI->findCaseValue(Cond));
+      ValueMap[OldTI] = new BranchInst(Dest, NewBB);
+      CloneBlock(Dest);
+      TerminatorDone = true;
+    }
+  }
+  
+  if (!TerminatorDone) {
+    Instruction *NewInst = OldTI->clone();
+    if (OldTI->hasName())
+      NewInst->setName(OldTI->getName()+NameSuffix);
+    NewBB->getInstList().push_back(NewInst);
+    ValueMap[OldTI] = NewInst;             // Add instruction map to value.
+    
+    // Recursively clone any reachable successor blocks.
+    const TerminatorInst *TI = BB->getTerminator();
+    for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
+      CloneBlock(TI->getSuccessor(i));
+  }
+  
   if (CodeInfo) {
     CodeInfo->ContainsCalls          |= hasCalls;
-    CodeInfo->ContainsUnwinds        |= isa<UnwindInst>(BB->getTerminator());
+    CodeInfo->ContainsUnwinds        |= isa<UnwindInst>(OldTI);
     CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas;
     CodeInfo->ContainsDynamicAllocas |= hasStaticAllocas && 
       BB != &BB->getParent()->front();
@@ -229,11 +272,6 @@
   
   if (ReturnInst *RI = dyn_cast<ReturnInst>(NewBB->getTerminator()))
     Returns.push_back(RI);
-  
-  // Recursively clone any reachable successor blocks.
-  const TerminatorInst *TI = BB->getTerminator();
-  for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i)
-    CloneBlock(TI->getSuccessor(i));
 }
 
 /// ConstantFoldMappedInstruction - Constant fold the specified instruction,
@@ -260,6 +298,7 @@
   return ConstantFoldInstOperands(I->getOpcode(), I->getType(), Ops);
 }
 
+#include <iostream>
 
 /// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto,
 /// except that it does some simple constant prop and DCE on the fly.  The
@@ -291,11 +330,13 @@
   // reachable, we have cloned it and the old block is now in the value map:
   // insert it into the new function in the right order.  If not, ignore it.
   //
+  // Defer PHI resolution until rest of function is resolved.
+  std::vector<const PHINode*> PHIToResolve;
   for (Function::const_iterator BI = OldFunc->begin(), BE = OldFunc->end();
        BI != BE; ++BI) {
     BasicBlock *NewBB = cast_or_null<BasicBlock>(ValueMap[BI]);
     if (NewBB == 0) continue;  // Dead block.
-    
+
     // Add the new block to the new function.
     NewFunc->getBasicBlockList().push_back(NewBB);
     
@@ -307,27 +348,109 @@
     // Handle PHI nodes specially, as we have to remove references to dead
     // blocks.
     if (PHINode *PN = dyn_cast<PHINode>(I)) {
-      unsigned NumPreds = PN->getNumIncomingValues();
-      for (; (PN = dyn_cast<PHINode>(I)); ++I) {
-        for (unsigned pred = 0, e = NumPreds; pred != e; ++pred) {
-          if (BasicBlock *MappedBlock = 
-               cast_or_null<BasicBlock>(ValueMap[PN->getIncomingBlock(pred)])) {
-            Value *InVal = MapValue(PN->getIncomingValue(pred), ValueMap);
-            assert(InVal && "Unknown input value?");
-            PN->setIncomingValue(pred, InVal);
-            PN->setIncomingBlock(pred, MappedBlock);
-          } else {
-            PN->removeIncomingValue(pred, false);
-            --pred, --e;  // Revisit the next entry.
-          }
-        }
-      }
+      // Skip over all PHI nodes, remembering them for later.
+      BasicBlock::const_iterator OldI = BI->begin();
+      for (; (PN = dyn_cast<PHINode>(I)); ++I, ++OldI)
+        PHIToResolve.push_back(cast<PHINode>(OldI));
     }
     
     // Otherwise, remap the rest of the instructions normally.
     for (; I != NewBB->end(); ++I)
       RemapInstruction(I, ValueMap);
   }
+  
+  // Defer PHI resolution until rest of function is resolved, PHI resolution
+  // requires the CFG to be up-to-date.
+  for (unsigned phino = 0, e = PHIToResolve.size(); phino != e; ) {
+    const PHINode *OPN = PHIToResolve[phino];
+    
+    unsigned NumPreds = OPN->getNumIncomingValues();
+    
+    unsigned BBPHIStart = phino;
+    const BasicBlock *OldBB = OPN->getParent();
+    BasicBlock *NewBB = cast<BasicBlock>(ValueMap[OldBB]);
+
+    // Map operands for blocks that are live and remove operands for blocks
+    // that are dead.
+    for (; phino != PHIToResolve.size() &&
+         PHIToResolve[phino]->getParent() == OldBB; ++phino) {
+      OPN = PHIToResolve[phino];
+      PHINode *PN = cast<PHINode>(ValueMap[OPN]);
+      for (unsigned pred = 0, e = NumPreds; pred != e; ++pred) {
+        if (BasicBlock *MappedBlock = 
+            cast_or_null<BasicBlock>(ValueMap[PN->getIncomingBlock(pred)])) {
+          Value *InVal = MapValue(PN->getIncomingValue(pred), ValueMap);
+          assert(InVal && "Unknown input value?");
+          PN->setIncomingValue(pred, InVal);
+          PN->setIncomingBlock(pred, MappedBlock);
+        } else {
+          PN->removeIncomingValue(pred, false);
+          --pred, --e;  // Revisit the next entry.
+        }
+      } 
+    }
+    
+    // The loop above has removed PHI entries for those blocks that are dead
+    // and has updated others.  However, if a block is live (i.e. copied over)
+    // but its terminator has been changed to not go to this block, then our
+    // phi nodes will have invalid entries.  Update the PHI nodes in this
+    // case.
+    PHINode *PN = cast<PHINode>(NewBB->begin());
+    NumPreds = std::distance(pred_begin(NewBB), pred_end(NewBB));
+    if (NumPreds != PN->getNumIncomingValues()) {
+      assert(NumPreds < PN->getNumIncomingValues());
+      // Count how many times each predecessor comes to this block.
+      std::map<BasicBlock*, unsigned> PredCount;
+      for (pred_iterator PI = pred_begin(NewBB), E = pred_end(NewBB);
+           PI != E; ++PI)
+        --PredCount[*PI];
+      
+      // Figure out how many entries to remove from each PHI.
+      for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
+        ++PredCount[PN->getIncomingBlock(i)];
+      
+      // At this point, the excess predecessor entries are positive in the
+      // map.  Loop over all of the PHIs and remove excess predecessor
+      // entries.
+      BasicBlock::iterator I = NewBB->begin();
+      for (; (PN = dyn_cast<PHINode>(I)); ++I) {
+        for (std::map<BasicBlock*, unsigned>::iterator PCI =PredCount.begin(),
+             E = PredCount.end(); PCI != E; ++PCI) {
+          BasicBlock *Pred     = PCI->first;
+          for (unsigned NumToRemove = PCI->second; NumToRemove; --NumToRemove)
+            PN->removeIncomingValue(Pred, false);
+        }
+      }
+    }
+    
+    // If the loops above have made these phi nodes have 0 or 1 operand,
+    // replace them with undef or the input value.  We must do this for
+    // correctness, because 0-operand phis are not valid.
+    PN = cast<PHINode>(NewBB->begin());
+    if (PN->getNumIncomingValues() == 0) {
+      BasicBlock::iterator I = NewBB->begin();
+      BasicBlock::const_iterator OldI = OldBB->begin();
+      while ((PN = dyn_cast<PHINode>(I++))) {
+        Value *NV = UndefValue::get(PN->getType());
+        PN->replaceAllUsesWith(NV);
+        assert(ValueMap[OldI] == PN && "ValueMap mismatch");
+        ValueMap[OldI] = NV;
+        PN->eraseFromParent();
+        ++OldI;
+      }
+    } else if (PN->getNumIncomingValues() == 1) {
+      BasicBlock::iterator I = NewBB->begin();
+      BasicBlock::const_iterator OldI = OldBB->begin();
+      while ((PN = dyn_cast<PHINode>(I++))) {
+        Value *NV = PN->getIncomingValue(0);
+        PN->replaceAllUsesWith(NV);
+        assert(ValueMap[OldI] == PN && "ValueMap mismatch");
+        ValueMap[OldI] = NV;
+        PN->eraseFromParent();
+        ++OldI;
+      }
+    }
+  }
 }
 
 






More information about the llvm-commits mailing list