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

Chris Lattner lattner at cs.uiuc.edu
Sun Sep 19 11:52:04 PDT 2004



Changes in directory llvm/lib/Transforms/Utils:

PromoteMemoryToRegister.cpp updated: 1.69 -> 1.70
---
Log message:

Remove a whole bunch of horrible hacky code that was used to promote allocas
whose addresses where used by trivial phi nodes and select instructions.  This
is now performed by the instcombine pass, which is more powerful, is much
simpler, and is faster.  This allows the deletion of a bunch of code, two
FIXME's and two gotos.



---
Diffs of the changes:  (+7 -145)

Index: llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
diff -u llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.69 llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.70
--- llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp:1.69	Fri Sep 17 19:32:40 2004
+++ llvm/lib/Transforms/Utils/PromoteMemoryToRegister.cpp	Sun Sep 19 13:51:51 2004
@@ -8,11 +8,11 @@
 //===----------------------------------------------------------------------===//
 //
 // This file promote memory references to be register references.  It promotes
-// alloca instructions which only have loads and stores as uses (or that have
-// PHI nodes which are only loaded from).  An alloca is transformed by using
-// dominator frontiers to place PHI nodes, then traversing the function in
-// depth-first order to rewrite loads and stores as appropriate.  This is just
-// the standard SSA construction algorithm to construct "pruned" SSA form.
+// alloca instructions which only have loads and stores as uses.  An alloca is
+// transformed by using dominator frontiers to place PHI nodes, then traversing
+// the function in depth-first order to rewrite loads and stores as appropriate.
+// This is just the standard SSA construction algorithm to construct "pruned"
+// SSA form.
 //
 //===----------------------------------------------------------------------===//
 
@@ -30,8 +30,7 @@
 using namespace llvm;
 
 /// isAllocaPromotable - Return true if this alloca is legal for promotion.
-/// This is true if there are only loads and stores to the alloca... of if there
-/// is a PHI node using the address which can be trivially transformed.
+/// This is true if there are only loads and stores to the alloca.
 ///
 bool llvm::isAllocaPromotable(const AllocaInst *AI, const TargetData &TD) {
   // FIXME: If the memory unit is of pointer or integer type, we can permit
@@ -45,72 +44,8 @@
     } else if (const StoreInst *SI = dyn_cast<StoreInst>(*UI)) {
       if (SI->getOperand(0) == AI)
         return false;   // Don't allow a store OF the AI, only INTO the AI.
-    } else if (const PHINode *PN = dyn_cast<PHINode>(*UI)) {
-      // We only support PHI nodes in a few simple cases.  The PHI node is only
-      // allowed to have one use, which must be a load instruction, and can only
-      // use alloca instructions (no random pointers).  Also, there cannot be
-      // any accesses to AI between the PHI node and the use of the PHI.
-      if (!PN->hasOneUse()) return false;
-
-      // Our transformation causes the unconditional loading of all pointer
-      // operands to the PHI node.  Because this could cause a fault if there is
-      // a critical edge in the CFG and if one of the pointers is illegal, we
-      // refuse to promote PHI nodes unless they are obviously safe.  For now,
-      // obviously safe means that all of the operands are allocas.
-      //
-      // If we wanted to extend this code to break critical edges, this
-      // restriction could be relaxed, and we could even handle uses of the PHI
-      // node that are volatile loads or stores.
-      //
-      for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
-        if (!isa<AllocaInst>(PN->getIncomingValue(i)))
-          return false;
-      
-      // Now make sure the one user instruction is in the same basic block as
-      // the PHI, and that there are no loads or stores between the PHI node and
-      // the access.
-      BasicBlock::const_iterator UI = cast<Instruction>(PN->use_back());
-      if (!isa<LoadInst>(UI) || cast<LoadInst>(UI)->isVolatile()) return false;
-      
-      // Scan looking for memory accesses.
-      // FIXME: this should REALLY use alias analysis.
-      for (--UI; !isa<PHINode>(UI); --UI)
-        if (isa<LoadInst>(UI) || isa<StoreInst>(UI) || isa<CallInst>(UI))
-          return false;
-
-      // If we got this far, we can promote the PHI use.
-    } else if (const SelectInst *SI = dyn_cast<SelectInst>(*UI)) {
-      // We only support selects in a few simple cases.  The select is only
-      // allowed to have one use, which must be a load instruction, and can only
-      // use alloca instructions (no random pointers).  Also, there cannot be
-      // any accesses to AI between the PHI node and the use of the PHI.
-      if (!SI->hasOneUse()) return false;
-
-      // Our transformation causes the unconditional loading of all pointer
-      // operands of the select.  Because this could cause a fault if there is a
-      // critical edge in the CFG and if one of the pointers is illegal, we
-      // refuse to promote the select unless it is obviously safe.  For now,
-      // obviously safe means that all of the operands are allocas.
-      //
-      if (!isa<AllocaInst>(SI->getOperand(1)) ||
-          !isa<AllocaInst>(SI->getOperand(2)))
-        return false;
-      
-      // Now make sure the one user instruction is in the same basic block as
-      // the PHI, and that there are no loads or stores between the PHI node and
-      // the access.
-      BasicBlock::const_iterator UI = cast<Instruction>(SI->use_back());
-      if (!isa<LoadInst>(UI) || cast<LoadInst>(UI)->isVolatile()) return false;
-      
-      // Scan looking for memory accesses.
-      // FIXME: this should REALLY use alias analysis.
-      for (--UI; &*UI != SI; --UI)
-        if (isa<LoadInst>(UI) || isa<StoreInst>(UI) || isa<CallInst>(UI))
-          return false;
-
-      // If we got this far, we can promote the select use.
     } else {
-      return false;   // Not a load, store, or promotable PHI?
+      return false;   // Not a load or store.
     }
   
   return true;
@@ -216,7 +151,6 @@
     // As we scan the uses of the alloca instruction, keep track of stores, and
     // decide whether all of the loads and stores to the alloca are within the
     // same basic block.
-  RestartUseScan:
     Value *AllocaPointerVal = 0;
     for (Value::use_iterator U =AI->use_begin(), E = AI->use_end(); U != E;++U){
       Instruction *User = cast<Instruction>(*U);
@@ -228,78 +162,6 @@
         // Otherwise it must be a load instruction, keep track of variable reads
         UsingBlocks.push_back(LI->getParent());
         AllocaPointerVal = LI;
-      } else if (SelectInst *SI = dyn_cast<SelectInst>(User)) {
-        // Because of the restrictions we placed on Select instruction uses
-        // above things are very simple.  Transform the select of addresses into
-        // a select of loaded values.
-        LoadInst *Load = cast<LoadInst>(SI->use_back());
-        std::string LoadName = Load->getName(); Load->setName("");
-
-        Value *TrueVal = new LoadInst(SI->getOperand(1), 
-                                      SI->getOperand(1)->getName()+".val", SI);
-        Value *FalseVal = new LoadInst(SI->getOperand(2), 
-                                       SI->getOperand(2)->getName()+".val", SI);
-
-        Value *NewSI = new SelectInst(SI->getOperand(0), TrueVal,
-                                      FalseVal, Load->getName(), SI);
-        if (AST && isa<PointerType>(Load->getType())) {
-          AST->copyValue(Load, TrueVal);
-          AST->copyValue(Load, FalseVal);
-          AST->copyValue(Load, NewSI);
-          AST->deleteValue(Load);
-          AST->deleteValue(SI);
-        }
-
-        Load->replaceAllUsesWith(NewSI);
-        Load->getParent()->getInstList().erase(Load);
-        SI->getParent()->getInstList().erase(SI);
-
-        // Restart our scan of uses...
-        DefiningBlocks.clear();
-        UsingBlocks.clear();
-        goto RestartUseScan;
-      } else {
-        // Because of the restrictions we placed on PHI node uses above, the PHI
-        // node reads the block in any using predecessors.  Transform the PHI of
-        // addresses into a PHI of loaded values.
-        PHINode *PN = cast<PHINode>(User);
-        assert(PN->hasOneUse() && "Cannot handle PHI Node with != 1 use!");
-        LoadInst *PNUser = cast<LoadInst>(PN->use_back());
-        std::string PNUserName = PNUser->getName(); PNUser->setName("");
-
-        // Create the new PHI node and insert load instructions as appropriate.
-        PHINode *NewPN = new PHINode(AI->getAllocatedType(), PNUserName, PN);
-        std::map<BasicBlock*, LoadInst*> NewLoads;
-        for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
-          BasicBlock *Pred = PN->getIncomingBlock(i);
-          LoadInst *&NewLoad = NewLoads[Pred];
-          if (NewLoad == 0)  // Insert the new load in the predecessor
-            NewLoad = new LoadInst(PN->getIncomingValue(i),
-                                   PN->getIncomingValue(i)->getName()+".val",
-                                   Pred->getTerminator());
-          NewPN->addIncoming(NewLoad, Pred);
-        }
-
-        if (AST && isa<PointerType>(NewPN->getType())) {
-          for (std::map<BasicBlock*, LoadInst*>::iterator I = NewLoads.begin(),
-                 E = NewLoads.end(); I != E; ++I)
-            AST->copyValue(PNUser, I->second);
-          AST->copyValue(PNUser, NewPN);
-          AST->deleteValue(PNUser);
-          AST->deleteValue(PN);
-        }
-
-        // Remove the old load.
-        PNUser->replaceAllUsesWith(NewPN);
-        PNUser->getParent()->getInstList().erase(PNUser);
-
-        // Remove the old PHI node.
-        PN->getParent()->getInstList().erase(PN);
-
-        // Restart our scan of uses...
-        DefiningBlocks.clear();
-        UsingBlocks.clear();
-        goto RestartUseScan;
       }
 
       if (OnlyUsedInOneBlock) {






More information about the llvm-commits mailing list