<div class="gmail_quote">On 14 January 2011 16:12, Chris Lattner <span dir="ltr"><<a href="mailto:sabre@nondot.org">sabre@nondot.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Author: lattner<br>
Date: Fri Jan 14 18:12:35 2011<br>
New Revision: 123501<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=123501&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=123501&view=rev</a><br>
Log:<br>
Generalize LoadAndStorePromoter a bit and switch LICM<br>
to use it.<br>
<br>
Modified:<br>
llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h<br>
llvm/trunk/lib/Transforms/Scalar/LICM.cpp<br>
llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp<br>
llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h?rev=123501&r1=123500&r2=123501&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h?rev=123501&r1=123500&r2=123501&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h (original)<br>
+++ llvm/trunk/include/llvm/Transforms/Utils/SSAUpdater.h Fri Jan 14 18:12:35 2011<br>
@@ -118,15 +118,17 @@<br>
/// virtual methods.<br>
///<br>
class LoadAndStorePromoter {<br>
+protected:<br>
+ SSAUpdater &SSA;<br>
public:<br>
- LoadAndStorePromoter() {}<br>
+ LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts,<br>
+ SSAUpdater &S, StringRef Name = StringRef());<br>
virtual ~LoadAndStorePromoter() {}<br>
<br>
/// run - This does the promotion. Insts is a list of loads and stores to<br>
/// promote, and Name is the basename for the PHIs to insert. After this is<br>
/// complete, the loads and stores are removed from the code.<br>
- void run(StringRef Name, const SmallVectorImpl<Instruction*> &Insts,<br>
- SSAUpdater *SSA = 0);<br>
+ void run(const SmallVectorImpl<Instruction*> &Insts) const;<br>
<br>
<br>
/// Return true if the specified instruction is in the Inst list (which was<br>
@@ -139,6 +141,21 @@<br>
return true;<br>
return false;<br>
}<br>
+<br>
+ /// doExtraRewritesBeforeFinalDeletion - This hook is invoked after all the<br>
+ /// stores are found and inserted as available values, but<br></blockquote><div><br>But what?<br><br>NIck<br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
+ virtual void doExtraRewritesBeforeFinalDeletion() const {<br>
+ }<br>
+<br>
+ /// replaceLoadWithValue - Clients can choose to implement this to get<br>
+ /// notified right before a load is RAUW'd another value.<br>
+ virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const {<br>
+ }<br>
+<br>
+ /// This is called before each instruction is deleted.<br>
+ virtual void instructionDeleted(Instruction *I) const {<br>
+ }<br>
+<br>
};<br>
<br>
} // End llvm namespace<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=123501&r1=123500&r2=123501&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=123501&r1=123500&r2=123501&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Fri Jan 14 18:12:35 2011<br>
@@ -595,6 +595,53 @@<br>
return true;<br>
}<br>
<br>
+namespace {<br>
+ class LoopPromoter : public LoadAndStorePromoter {<br>
+ Value *SomePtr; // Designated pointer to store to.<br>
+ SmallPtrSet<Value*, 4> &PointerMustAliases;<br>
+ SmallVectorImpl<BasicBlock*> &LoopExitBlocks;<br>
+ AliasSetTracker &AST;<br>
+ public:<br>
+ LoopPromoter(Value *SP,<br>
+ const SmallVectorImpl<Instruction*> &Insts, SSAUpdater &S,<br>
+ SmallPtrSet<Value*, 4> &PMA,<br>
+ SmallVectorImpl<BasicBlock*> &LEB, AliasSetTracker &ast)<br>
+ : LoadAndStorePromoter(Insts, S), SomePtr(SP), PointerMustAliases(PMA),<br>
+ LoopExitBlocks(LEB), AST(ast) {}<br>
+<br>
+ virtual bool isInstInList(Instruction *I,<br>
+ const SmallVectorImpl<Instruction*> &) const {<br>
+ Value *Ptr;<br>
+ if (LoadInst *LI = dyn_cast<LoadInst>(I))<br>
+ Ptr = LI->getOperand(0);<br>
+ else<br>
+ Ptr = cast<StoreInst>(I)->getPointerOperand();<br>
+ return PointerMustAliases.count(Ptr);<br>
+ }<br>
+<br>
+ virtual void doExtraRewritesBeforeFinalDeletion() const {<br>
+ // Insert stores after in the loop exit blocks. Each exit block gets a<br>
+ // store of the live-out values that feed them. Since we've already told<br>
+ // the SSA updater about the defs in the loop and the preheader<br>
+ // definition, it is all set and we can start using it.<br>
+ for (unsigned i = 0, e = LoopExitBlocks.size(); i != e; ++i) {<br>
+ BasicBlock *ExitBlock = LoopExitBlocks[i];<br>
+ Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);<br>
+ Instruction *InsertPos = ExitBlock->getFirstNonPHI();<br>
+ new StoreInst(LiveInValue, SomePtr, InsertPos);<br>
+ }<br>
+ }<br>
+<br>
+ virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const {<br>
+ // Update alias analysis.<br>
+ AST.copyValue(LI, V);<br>
+ }<br>
+ virtual void instructionDeleted(Instruction *I) const {<br>
+ AST.deleteValue(I);<br>
+ }<br>
+ };<br>
+} // end anon namespace<br>
+<br>
/// PromoteAliasSet - Try to promote memory values to scalars by sinking<br>
/// stores out of the loop and moving loads to before the loop. We do this by<br>
/// looping over the stores in the loop, looking for stores to Must pointers<br>
@@ -679,179 +726,43 @@<br>
Changed = true;<br>
++NumPromoted;<br>
<br>
+ SmallVector<BasicBlock*, 8> ExitBlocks;<br>
+ CurLoop->getUniqueExitBlocks(ExitBlocks);<br>
+<br>
// We use the SSAUpdater interface to insert phi nodes as required.<br>
SmallVector<PHINode*, 16> NewPHIs;<br>
SSAUpdater SSA(&NewPHIs);<br>
+ LoopPromoter Promoter(SomePtr, LoopUses, SSA, PointerMustAliases, ExitBlocks,<br>
+ *CurAST);<br>
<br>
- // It wants to know some value of the same type as what we'll be inserting.<br>
- Value *SomeValue;<br>
- if (isa<LoadInst>(LoopUses[0]))<br>
- SomeValue = LoopUses[0];<br>
- else<br>
- SomeValue = cast<StoreInst>(LoopUses[0])->getOperand(0);<br>
- SSA.Initialize(SomeValue->getType(), SomeValue->getName());<br>
-<br>
- // First step: bucket up uses of the pointers by the block they occur in.<br>
- // This is important because we have to handle multiple defs/uses in a block<br>
- // ourselves: SSAUpdater is purely for cross-block references.<br>
- // FIXME: Want a TinyVector<Instruction*> since there is usually 0/1 element.<br>
- DenseMap<BasicBlock*, std::vector<Instruction*> > UsesByBlock;<br>
- for (unsigned i = 0, e = LoopUses.size(); i != e; ++i) {<br>
- Instruction *User = LoopUses[i];<br>
- UsesByBlock[User->getParent()].push_back(User);<br>
- }<br>
-<br>
- // Okay, now we can iterate over all the blocks in the loop with uses,<br>
- // processing them. Keep track of which loads are loading a live-in value.<br>
- SmallVector<LoadInst*, 32> LiveInLoads;<br>
- DenseMap<Value*, Value*> ReplacedLoads;<br>
-<br>
- for (unsigned LoopUse = 0, e = LoopUses.size(); LoopUse != e; ++LoopUse) {<br>
- Instruction *User = LoopUses[LoopUse];<br>
- std::vector<Instruction*> &BlockUses = UsesByBlock[User->getParent()];<br>
-<br>
- // If this block has already been processed, ignore this repeat use.<br>
- if (BlockUses.empty()) continue;<br>
-<br>
- // Okay, this is the first use in the block. If this block just has a<br>
- // single user in it, we can rewrite it trivially.<br>
- if (BlockUses.size() == 1) {<br>
- // If it is a store, it is a trivial def of the value in the block.<br>
- if (isa<StoreInst>(User)) {<br>
- SSA.AddAvailableValue(User->getParent(),<br>
- cast<StoreInst>(User)->getOperand(0));<br>
- } else {<br>
- // Otherwise it is a load, queue it to rewrite as a live-in load.<br>
- LiveInLoads.push_back(cast<LoadInst>(User));<br>
- }<br>
- BlockUses.clear();<br>
- continue;<br>
- }<br>
-<br>
- // Otherwise, check to see if this block is all loads. If so, we can queue<br>
- // them all as live in loads.<br>
- bool HasStore = false;<br>
- for (unsigned i = 0, e = BlockUses.size(); i != e; ++i) {<br>
- if (isa<StoreInst>(BlockUses[i])) {<br>
- HasStore = true;<br>
- break;<br>
- }<br>
- }<br>
-<br>
- if (!HasStore) {<br>
- for (unsigned i = 0, e = BlockUses.size(); i != e; ++i)<br>
- LiveInLoads.push_back(cast<LoadInst>(BlockUses[i]));<br>
- BlockUses.clear();<br>
- continue;<br>
- }<br>
-<br>
- // Otherwise, we have mixed loads and stores (or just a bunch of stores).<br>
- // Since SSAUpdater is purely for cross-block values, we need to determine<br>
- // the order of these instructions in the block. If the first use in the<br>
- // block is a load, then it uses the live in value. The last store defines<br>
- // the live out value. We handle this by doing a linear scan of the block.<br>
- BasicBlock *BB = User->getParent();<br>
- Value *StoredValue = 0;<br>
- for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E; ++II) {<br>
- if (LoadInst *L = dyn_cast<LoadInst>(II)) {<br>
- // If this is a load from an unrelated pointer, ignore it.<br>
- if (!PointerMustAliases.count(L->getOperand(0))) continue;<br>
-<br>
- // If we haven't seen a store yet, this is a live in use, otherwise<br>
- // use the stored value.<br>
- if (StoredValue) {<br>
- L->replaceAllUsesWith(StoredValue);<br>
- ReplacedLoads[L] = StoredValue;<br>
- } else {<br>
- LiveInLoads.push_back(L);<br>
- }<br>
- continue;<br>
- }<br>
-<br>
- if (StoreInst *S = dyn_cast<StoreInst>(II)) {<br>
- // If this is a store to an unrelated pointer, ignore it.<br>
- if (!PointerMustAliases.count(S->getOperand(1))) continue;<br>
-<br>
- // Remember that this is the active value in the block.<br>
- StoredValue = S->getOperand(0);<br>
- }<br>
- }<br>
-<br>
- // The last stored value that happened is the live-out for the block.<br>
- assert(StoredValue && "Already checked that there is a store in block");<br>
- SSA.AddAvailableValue(BB, StoredValue);<br>
- BlockUses.clear();<br>
- }<br>
-<br>
- // Now that all the intra-loop values are classified, set up the preheader.<br>
- // It gets a load of the pointer we're promoting, and it is the live-out value<br>
- // from the preheader.<br>
- LoadInst *PreheaderLoad = new LoadInst(SomePtr,SomePtr->getName()+".promoted",<br>
- Preheader->getTerminator());<br>
+ // Set up the preheader to have a definition of the value. It is the live-out<br>
+ // value from the preheader that uses in the loop will use.<br>
+ LoadInst *PreheaderLoad =<br>
+ new LoadInst(SomePtr, SomePtr->getName()+".promoted",<br>
+ Preheader->getTerminator());<br>
SSA.AddAvailableValue(Preheader, PreheaderLoad);<br>
<br>
- // Now that the preheader is good to go, set up the exit blocks. Each exit<br>
- // block gets a store of the live-out values that feed them. Since we've<br>
- // already told the SSA updater about the defs in the loop and the preheader<br>
- // definition, it is all set and we can start using it.<br>
- SmallVector<BasicBlock*, 8> ExitBlocks;<br>
- CurLoop->getUniqueExitBlocks(ExitBlocks);<br>
- for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {<br>
- BasicBlock *ExitBlock = ExitBlocks[i];<br>
- Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);<br>
- Instruction *InsertPos = ExitBlock->getFirstNonPHI();<br>
- new StoreInst(LiveInValue, SomePtr, InsertPos);<br>
+ // Copy any value stored to or loaded from a must-alias of the pointer.<br>
+ if (PreheaderLoad->getType()->isPointerTy()) {<br>
+ Value *SomeValue;<br>
+ if (LoadInst *LI = dyn_cast<LoadInst>(LoopUses[0]))<br>
+ SomeValue = LI;<br>
+ else<br>
+ SomeValue = cast<StoreInst>(LoopUses[0])->getValueOperand();<br>
+<br>
+ CurAST->copyValue(SomeValue, PreheaderLoad);<br>
}<br>
<br>
- // Okay, now we rewrite all loads that use live-in values in the loop,<br>
- // inserting PHI nodes as necessary.<br>
- for (unsigned i = 0, e = LiveInLoads.size(); i != e; ++i) {<br>
- LoadInst *ALoad = LiveInLoads[i];<br>
- Value *NewVal = SSA.GetValueInMiddleOfBlock(ALoad->getParent());<br>
- ALoad->replaceAllUsesWith(NewVal);<br>
- CurAST->copyValue(ALoad, NewVal);<br>
- ReplacedLoads[ALoad] = NewVal;<br>
- }<br>
+ // Rewrite all the loads in the loop and remember all the definitions from<br>
+ // stores in the loop.<br>
+ Promoter.run(LoopUses);<br>
<br>
// If the preheader load is itself a pointer, we need to tell alias analysis<br>
// about the new pointer we created in the preheader block and about any PHI<br>
// nodes that just got inserted.<br>
if (PreheaderLoad->getType()->isPointerTy()) {<br>
- // Copy any value stored to or loaded from a must-alias of the pointer.<br>
- CurAST->copyValue(SomeValue, PreheaderLoad);<br>
-<br>
for (unsigned i = 0, e = NewPHIs.size(); i != e; ++i)<br>
- CurAST->copyValue(SomeValue, NewPHIs[i]);<br>
- }<br>
-<br>
- // Now that everything is rewritten, delete the old instructions from the body<br>
- // of the loop. They should all be dead now.<br>
- for (unsigned i = 0, e = LoopUses.size(); i != e; ++i) {<br>
- Instruction *User = LoopUses[i];<br>
-<br>
- // If this is a load that still has uses, then the load must have been added<br>
- // as a live value in the SSAUpdate data structure for a block (e.g. because<br>
- // the loaded value was stored later). In this case, we need to recursively<br>
- // propagate the updates until we get to the real value.<br>
- if (!User->use_empty()) {<br>
- Value *NewVal = ReplacedLoads[User];<br>
- assert(NewVal && "not a replaced load?");<br>
-<br>
- // Propagate down to the ultimate replacee. The intermediately loads<br>
- // could theoretically already have been deleted, so we don't want to<br>
- // dereference the Value*'s.<br>
- DenseMap<Value*, Value*>::iterator RLI = ReplacedLoads.find(NewVal);<br>
- while (RLI != ReplacedLoads.end()) {<br>
- NewVal = RLI->second;<br>
- RLI = ReplacedLoads.find(NewVal);<br>
- }<br>
-<br>
- User->replaceAllUsesWith(NewVal);<br>
- CurAST->copyValue(User, NewVal);<br>
- }<br>
-<br>
- CurAST->deleteValue(User);<br>
- User->eraseFromParent();<br>
+ CurAST->copyValue(PreheaderLoad, NewPHIs[i]);<br>
}<br>
<br>
// fwew, we're done!<br>
<br>
Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=123501&r1=123500&r2=123501&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=123501&r1=123500&r2=123501&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Fri Jan 14 18:12:35 2011<br>
@@ -844,20 +844,13 @@<br>
class AllocaPromoter : public LoadAndStorePromoter {<br>
AllocaInst *AI;<br>
public:<br>
- AllocaPromoter() : AI(0) {}<br>
+ AllocaPromoter(const SmallVectorImpl<Instruction*> &Insts, SSAUpdater &S)<br>
+ : LoadAndStorePromoter(Insts, S), AI(0) {}<br>
<br>
- void run(AllocaInst *AI, SSAUpdater &SSA) {<br>
+ void run(AllocaInst *AI, const SmallVectorImpl<Instruction*> &Insts) {<br>
// Remember which alloca we're promoting (for isInstInList).<br>
this->AI = AI;<br>
-<br>
- // Build the list of instructions to promote.<br>
- SmallVector<Instruction*, 64> Insts;<br>
- for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();<br>
- UI != E; ++UI)<br>
- Insts.push_back(cast<Instruction>(*UI));<br>
-<br>
- LoadAndStorePromoter::run(AI->getName(), Insts, &SSA);<br>
-<br>
+ LoadAndStorePromoter::run(Insts);<br>
AI->eraseFromParent();<br>
}<br>
<br>
@@ -882,7 +875,7 @@<br>
BasicBlock &BB = F.getEntryBlock(); // Get the entry node for the function<br>
<br>
bool Changed = false;<br>
-<br>
+ SmallVector<Instruction*, 64> Insts;<br>
while (1) {<br>
Allocas.clear();<br>
<br>
@@ -899,9 +892,17 @@<br>
PromoteMemToReg(Allocas, *DT, *DF);<br>
else {<br>
SSAUpdater SSA;<br>
- AllocaPromoter Promoter;<br>
- for (unsigned i = 0, e = Allocas.size(); i != e; ++i)<br>
- Promoter.run(Allocas[i], SSA);<br>
+ for (unsigned i = 0, e = Allocas.size(); i != e; ++i) {<br>
+ AllocaInst *AI = Allocas[i];<br>
+<br>
+ // Build list of instructions to promote.<br>
+ for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();<br>
+ UI != E; ++UI)<br>
+ Insts.push_back(cast<Instruction>(*UI));<br>
+<br>
+ AllocaPromoter(Insts, SSA).run(AI, Insts);<br>
+ Insts.clear();<br>
+ }<br>
}<br>
NumPromoted += Allocas.size();<br>
Changed = true;<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp?rev=123501&r1=123500&r2=123501&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp?rev=123501&r1=123500&r2=123501&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp Fri Jan 14 18:12:35 2011<br>
@@ -348,23 +348,25 @@<br>
// LoadAndStorePromoter Implementation<br>
//===----------------------------------------------------------------------===//<br>
<br>
-void LoadAndStorePromoter::run(StringRef BaseName,<br>
- const SmallVectorImpl<Instruction*> &Insts,<br>
- SSAUpdater *SSA) {<br>
+LoadAndStorePromoter::<br>
+LoadAndStorePromoter(const SmallVectorImpl<Instruction*> &Insts,<br>
+ SSAUpdater &S, StringRef BaseName) : SSA(S) {<br>
if (Insts.empty()) return;<br>
<br>
- // If no SSAUpdater was provided, use a default one. This allows the client<br>
- // to capture inserted PHI nodes etc if they want.<br>
- SSAUpdater DefaultSSA;<br>
- if (SSA == 0) SSA = &DefaultSSA;<br>
-<br>
- const Type *ValTy;<br>
+ Value *SomeVal;<br>
if (LoadInst *LI = dyn_cast<LoadInst>(Insts[0]))<br>
- ValTy = LI->getType();<br>
+ SomeVal = LI;<br>
else<br>
- ValTy = cast<StoreInst>(Insts[0])->getOperand(0)->getType();<br>
-<br>
- SSA->Initialize(ValTy, BaseName);<br>
+ SomeVal = cast<StoreInst>(Insts[0])->getOperand(0);<br>
+<br>
+ if (BaseName.empty())<br>
+ BaseName = SomeVal->getName();<br>
+ SSA.Initialize(SomeVal->getType(), BaseName);<br>
+}<br>
+<br>
+<br>
+void LoadAndStorePromoter::<br>
+run(const SmallVectorImpl<Instruction*> &Insts) const {<br>
<br>
// First step: bucket up uses of the alloca by the block they occur in.<br>
// This is important because we have to handle multiple defs/uses in a block<br>
@@ -396,7 +398,7 @@<br>
if (BlockUses.size() == 1) {<br>
// If it is a store, it is a trivial def of the value in the block.<br>
if (StoreInst *SI = dyn_cast<StoreInst>(User))<br>
- SSA->AddAvailableValue(BB, SI->getOperand(0));<br>
+ SSA.AddAvailableValue(BB, SI->getOperand(0));<br>
else<br>
// Otherwise it is a load, queue it to rewrite as a live-in load.<br>
LiveInLoads.push_back(cast<LoadInst>(User));<br>
@@ -437,6 +439,7 @@<br>
// If we haven't seen a store yet, this is a live in use, otherwise<br>
// use the stored value.<br>
if (StoredValue) {<br>
+ replaceLoadWithValue(L, StoredValue);<br>
L->replaceAllUsesWith(StoredValue);<br>
ReplacedLoads[L] = StoredValue;<br>
} else {<br>
@@ -456,7 +459,7 @@<br>
<br>
// The last stored value that happened is the live-out for the block.<br>
assert(StoredValue && "Already checked that there is a store in block");<br>
- SSA->AddAvailableValue(BB, StoredValue);<br>
+ SSA.AddAvailableValue(BB, StoredValue);<br>
BlockUses.clear();<br>
}<br>
<br>
@@ -464,11 +467,15 @@<br>
// inserting PHI nodes as necessary.<br>
for (unsigned i = 0, e = LiveInLoads.size(); i != e; ++i) {<br>
LoadInst *ALoad = LiveInLoads[i];<br>
- Value *NewVal = SSA->GetValueInMiddleOfBlock(ALoad->getParent());<br>
+ Value *NewVal = SSA.GetValueInMiddleOfBlock(ALoad->getParent());<br>
+ replaceLoadWithValue(ALoad, NewVal);<br>
ALoad->replaceAllUsesWith(NewVal);<br>
ReplacedLoads[ALoad] = NewVal;<br>
}<br>
<br>
+ // Allow the client to do stuff before we start nuking things.<br>
+ doExtraRewritesBeforeFinalDeletion();<br>
+<br>
// Now that everything is rewritten, delete the old instructions from the<br>
// function. They should all be dead now.<br>
for (unsigned i = 0, e = Insts.size(); i != e; ++i) {<br>
@@ -491,9 +498,11 @@<br>
RLI = ReplacedLoads.find(NewVal);<br>
}<br>
<br>
+ replaceLoadWithValue(cast<LoadInst>(User), NewVal);<br>
User->replaceAllUsesWith(NewVal);<br>
}<br>
<br>
+ instructionDeleted(User);<br>
User->eraseFromParent();<br>
}<br>
}<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br>