diff options
Diffstat (limited to 'lib/Transforms/Utils/PromoteMemoryToRegister.cpp')
-rw-r--r-- | lib/Transforms/Utils/PromoteMemoryToRegister.cpp | 152 |
1 files changed, 7 insertions, 145 deletions
diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index b4214ee09b..9edd864f55 100644 --- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -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 @@ bool llvm::isAllocaPromotable(const AllocaInst *AI, const TargetData &TD) { } 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 @@ void PromoteMem2Reg::run() { // 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 @@ void PromoteMem2Reg::run() { // 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) { |