summaryrefslogtreecommitdiff
path: root/lib/Transforms/Utils/PromoteMemoryToRegister.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-09-19 18:51:51 +0000
committerChris Lattner <sabre@nondot.org>2004-09-19 18:51:51 +0000
commita744b77e11a375927ffe6b807b99cd91cb55e2ba (patch)
treec24a11a5097157ff10664c2f1abed10aa45b8062 /lib/Transforms/Utils/PromoteMemoryToRegister.cpp
parent1fb6e41822b37dc54f57a6ea81593a508e52f5a3 (diff)
downloadllvm-a744b77e11a375927ffe6b807b99cd91cb55e2ba.tar.gz
llvm-a744b77e11a375927ffe6b807b99cd91cb55e2ba.tar.bz2
llvm-a744b77e11a375927ffe6b807b99cd91cb55e2ba.tar.xz
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@16406 91177308-0d34-0410-b5e6-96231b3b80d8
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) {