summaryrefslogtreecommitdiff
path: root/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Utils/PromoteMemoryToRegister.cpp')
-rw-r--r--lib/Transforms/Utils/PromoteMemoryToRegister.cpp152
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) {