Make the "pruning cloner" smarter. As it propagates constants through the
authorChris Lattner <sabre@nondot.org>
Thu, 1 Jun 2006 19:19:23 +0000 (19:19 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 1 Jun 2006 19:19:23 +0000 (19:19 +0000)
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.

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

lib/Transforms/Utils/CloneFunction.cpp

index dd1b31bde5ac3e077787a61c7d9b53d4b14043b5..fe232698830f48dc2fca00f7b570a9ada8f36ff2 100644 (file)
@@ -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 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB) {
   
   // 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 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB) {
     }
   }
   
+  // 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 @@ void PruningFunctionCloner::CloneBlock(const BasicBlock *BB) {
   
   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 @@ ConstantFoldMappedInstruction(const Instruction *I) {
   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 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
   // 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 @@ void llvm::CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc,
     // 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;
+      }
+    }
+  }
 }