diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index bbb131fabfb..e9ca9f15c3b 100644 --- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -31,46 +31,44 @@ using namespace std; namespace { -//instance of the promoter -- to keep all the local function data. +// instance of the promoter -- to keep all the local function data. // gets re-created for each function processed -class PromoteInstance -{ - protected: - vector Allocas; // the alloca instruction.. - map AllocaLookup; //reverse mapping of above +class PromoteInstance { +protected: + vector Allocas; // the alloca instruction.. + map AllocaLookup; // reverse mapping of above + + vector > WriteSets; // index corresponds to Allocas + vector > PhiNodes; // index corresponds to Allocas + vector > CurrentValue; // the current value stack + + //list of instructions to remove at end of pass :) + vector KillList; - vector > WriteSets; // index corresponds to Allocas - vector > PhiNodes; // index corresponds to Allocas - vector > CurrentValue; //the current value stack + set visited; // the basic blocks we've already visited + map > NewPhiNodes; // the phinodes we're adding - //list of instructions to remove at end of pass :) - vector killlist; - - set visited; //the basic blocks we've already visited - map > new_phinodes; //the phinodes we're adding - - - void traverse(BasicBlock *f, BasicBlock * predecessor); - bool PromoteFunction(Function *F, DominanceFrontier &DF); - bool queuePhiNode(BasicBlock *bb, int alloca_index); - void findSafeAllocas(Function *M); - bool didchange; - public: - // I do this so that I can force the deconstruction of the local variables - PromoteInstance(Function *F, DominanceFrontier &DF) - { - didchange=PromoteFunction(F, DF); - } - //This returns whether the pass changes anything - operator bool () { return didchange; } + void traverse(BasicBlock *f, BasicBlock * predecessor); + bool PromoteFunction(Function *F, DominanceFrontier &DF); + bool QueuePhiNode(BasicBlock *bb, unsigned alloca_index); + void findSafeAllocas(Function *M); + bool didchange; +public: + // I do this so that I can force the deconstruction of the local variables + PromoteInstance(Function *F, DominanceFrontier &DF) { + didchange = PromoteFunction(F, DF); + } + //This returns whether the pass changes anything + operator bool () { return didchange; } }; } // end of anonymous namespace + + // findSafeAllocas - Find allocas that are safe to promote // -void PromoteInstance::findSafeAllocas(Function *F) -{ +void PromoteInstance::findSafeAllocas(Function *F) { BasicBlock *BB = F->getEntryNode(); // Get the entry node for the function // Look at all instructions in the entry node @@ -84,224 +82,175 @@ void PromoteInstance::findSafeAllocas(Function *F) // Only allow nonindexed memory access instructions... if (MemAccessInst *MAI = dyn_cast(*UI)) { if (MAI->hasIndices()) { // indexed? - // Allow the access if there is only one index and the index is zero. + // Allow the access if there is only one index and the index is + // zero. if (*MAI->idx_begin() != ConstantUInt::get(Type::UIntTy, 0) || MAI->idx_begin()+1 != MAI->idx_end()) { - isSafe = false; break; + isSafe = false; + break; } } } else { isSafe = false; break; // Not a load or store? } } - if (isSafe) // If all checks pass, add alloca to safe list - { - AllocaLookup[AI]=Allocas.size(); - Allocas.push_back(AI); - } + if (isSafe) { // If all checks pass, add alloca to safe list + AllocaLookup[AI] = Allocas.size(); + Allocas.push_back(AI); + } } } -bool PromoteInstance::PromoteFunction(Function *F, DominanceFrontier & DF) { - // Calculate the set of safe allocas - findSafeAllocas(F); +bool PromoteInstance::PromoteFunction(Function *F, DominanceFrontier &DF) { + // Calculate the set of safe allocas + findSafeAllocas(F); - // Add each alloca to the killlist - // note: killlist is destroyed MOST recently added to least recently. - killlist.assign(Allocas.begin(), Allocas.end()); + // Add each alloca to the KillList. Note: KillList is destroyed MOST recently + // added to least recently. + KillList.assign(Allocas.begin(), Allocas.end()); - // Calculate the set of write-locations for each alloca. - // this is analogous to counting the number of 'redefinitions' of each variable. - for (unsigned i = 0; i()); //add a new set - for (Value::use_iterator U = AI->use_begin();U!=AI->use_end();++U) - { - if (MemAccessInst *MAI = dyn_cast(*U)) { - WriteSets[i].push_back(MAI->getParent()); // jot down the basic-block it came from - } - } - } + // Calculate the set of write-locations for each alloca. This is analogous to + // counting the number of 'redefinitions' of each variable. + WriteSets.resize(Allocas.size()); + for (unsigned i = 0; i != Allocas.size(); ++i) { + AllocaInst *AI = Allocas[i]; + for (Value::use_iterator U =AI->use_begin(), E = AI->use_end(); U != E; ++U) + if (StoreInst *SI = dyn_cast(*U)) + // jot down the basic-block it came from + WriteSets[i].push_back(SI->getParent()); + } - // Compute the locations where PhiNodes need to be inserted - // look at the dominance frontier of EACH basic-block we have a write in - PhiNodes.resize(Allocas.size()); - for (unsigned i = 0; isecond; - for (DominanceFrontier::DomSetType::iterator p = s.begin(); p!=s.end(); ++p) - { - if (queuePhiNode(*p,i)) - PhiNodes[i].push_back(*p); - } - } - } + // Compute the locations where PhiNodes need to be inserted. Look at the + // dominance frontier of EACH basic-block we have a write in + // + PhiNodes.resize(Allocas.size()); + for (unsigned i = 0; i != Allocas.size(); ++i) { + for (unsigned j = 0; j != WriteSets[i].size(); j++) { + // Look up the DF for this write, add it to PhiNodes + DominanceFrontier::const_iterator it = DF.find(WriteSets[i][j]); + DominanceFrontier::DomSetType S = it->second; + for (DominanceFrontier::DomSetType::iterator P = S.begin(), PE = S.end(); + P != PE; ++P) + QueuePhiNode(*P, i); + } + + // Perform iterative step + for (unsigned k = 0; k != PhiNodes[i].size(); k++) { + DominanceFrontier::const_iterator it = DF.find(PhiNodes[i][k]); + DominanceFrontier::DomSetType S = it->second; + for (DominanceFrontier::DomSetType::iterator P = S.begin(), PE = S.end(); + P != PE; ++P) + QueuePhiNode(*P, i); + } + } - // Walks all basic blocks in the function - // performing the SSA rename algorithm - // and inserting the phi nodes we marked as necessary - BasicBlock * f = F->front(); //get root basic-block + // Walks all basic blocks in the function performing the SSA rename algorithm + // and inserting the phi nodes we marked as necessary + // + CurrentValue.push_back(vector(Allocas.size())); + traverse(F->front(), 0); // there is no predecessor of the root node - CurrentValue.push_back(vector(Allocas.size())); + // Remove all instructions marked by being placed in the KillList... + // + while (!KillList.empty()) { + Instruction *I = KillList.back(); + KillList.pop_back(); - traverse(f, NULL); // there is no predecessor of the root node + //now go find.. + I->getParent()->getInstList().remove(I); + delete I; + } - - // ** REMOVE EVERYTHING IN THE KILL-LIST ** - // we need to kill 'uses' before root values - // so we should probably run through in reverse - for (vector::reverse_iterator i = killlist.rbegin(); i!=killlist.rend(); ++i) - { - Instruction * r = *i; - BasicBlock * o = r->getParent(); - //now go find.. - - BasicBlock::InstListType & l = o->getInstList(); - o->getInstList().remove(r); - delete r; - } - - return !Allocas.empty(); + return !Allocas.empty(); } +// QueuePhiNode - queues a phi-node to be added to a basic-block for a specific +// Alloca returns true if there wasn't already a phi-node for that variable +// +bool PromoteInstance::QueuePhiNode(BasicBlock *BB, unsigned i /*the alloca*/) { + // Look up the basic-block in question + vector &BBPNs = NewPhiNodes[BB]; + if (BBPNs.empty()) BBPNs.resize(Allocas.size()); -void PromoteInstance::traverse(BasicBlock *f, BasicBlock * predecessor) -{ - vector * tos = &CurrentValue.back(); //look at top- + // If the BB already has a phi node added for the i'th alloca then we're done! + if (BBPNs[i]) return false; - //if this is a BB needing a phi node, lookup/create the phinode for - // each variable we need phinodes for. - map >::iterator nd = new_phinodes.find(f); - if (nd!=new_phinodes.end()) - { - for (unsigned k = 0; k!=nd->second.size(); ++k) - if (nd->second[k]) - { - //at this point we can assume that the array has phi nodes.. let's - // add the incoming data - if ((*tos)[k]) - nd->second[k]->addIncoming((*tos)[k],predecessor); - //also note that the active variable IS designated by the phi node - (*tos)[k] = nd->second[k]; - } - } + // Create a phi-node using the dereferenced type... + PHINode *PN = new PHINode(Allocas[i]->getType()->getElementType(), + Allocas[i]->getName()+".mem2reg"); + BBPNs[i] = PN; - //don't revisit nodes - if (visited.find(f)!=visited.end()) - return; - //mark as visited - visited.insert(f); + // Add the phi-node to the basic-block + BB->getInstList().push_front(PN); - BasicBlock::iterator i = f->begin(); - //keep track of the value of each variable we're watching.. how? - while(i!=f->end()) - { - Instruction * inst = *i; //get the instruction - //is this a write/read? - if (LoadInst * LI = dyn_cast(inst)) - { - // This is a bit weird... - Value * ptr = LI->getPointerOperand(); //of type value - if (AllocaInst * srcinstr = dyn_cast(ptr)) - { - map::iterator ai = AllocaLookup.find(srcinstr); - if (ai!=AllocaLookup.end()) - { - if (Value *r = (*tos)[ai->second]) - { - //walk the use list of this load and replace - // all uses with r - LI->replaceAllUsesWith(r); - //now delete the instruction.. somehow.. - killlist.push_back((Instruction *)LI); - } - } - } - } - else if (StoreInst * SI = dyn_cast(inst)) - { - // delete this instruction and mark the name as the - // current holder of the value - Value * ptr = SI->getPointerOperand(); //of type value - if (Instruction * srcinstr = dyn_cast(ptr)) - { - map::iterator ai = AllocaLookup.find(srcinstr); - if (ai!=AllocaLookup.end()) - { - //what value were we writing? - Value * writeval = SI->getOperand(0); - //write down... - (*tos)[ai->second] = writeval; - //now delete it.. somehow? - killlist.push_back((Instruction *)SI); - } - } - - } - else if (TerminatorInst * TI = dyn_cast(inst)) - { - // Recurse across our sucessors - for (unsigned i = 0; i!=TI->getNumSuccessors(); i++) - { - CurrentValue.push_back(CurrentValue.back()); - traverse(TI->getSuccessor(i),f); //this node IS the predecessor - CurrentValue.pop_back(); - } - } - i++; - } + PhiNodes[i].push_back(BB); + return true; } -// queues a phi-node to be added to a basic-block for a specific Alloca -// returns true if there wasn't already a phi-node for that variable +void PromoteInstance::traverse(BasicBlock *BB, BasicBlock *Pred) { + vector &TOS = CurrentValue.back(); // look at top + // If this is a BB needing a phi node, lookup/create the phinode for each + // variable we need phinodes for. + vector &BBPNs = NewPhiNodes[BB]; + for (unsigned k = 0; k != BBPNs.size(); ++k) + if (BBPNs[k]) { + // at this point we can assume that the array has phi nodes.. let's add + // the incoming data + BBPNs[k]->addIncoming(TOS[k], Pred); -bool PromoteInstance::queuePhiNode(BasicBlock *bb, int i /*the alloca*/) -{ - map >::iterator nd; - //look up the basic-block in question - nd = new_phinodes.find(bb); - //if the basic-block has no phi-nodes added, or at least none - //for the i'th alloca. then add. - if (nd==new_phinodes.end() || nd->second[i]==NULL) - { - //we're not added any phi nodes to this basicblock yet - // create the phi-node array. - if (nd==new_phinodes.end()) - { - new_phinodes[bb] = vector(Allocas.size()); - nd = new_phinodes.find(bb); - } + // also note that the active variable IS designated by the phi node + TOS[k] = BBPNs[k]; + } - //find the type the alloca returns - const PointerType * pt = Allocas[i]->getType(); - //create a phi-node using the DEREFERENCED type - PHINode * ph = new PHINode(pt->getElementType(), Allocas[i]->getName()+".mem2reg"); - nd->second[i] = ph; - //add the phi-node to the basic-block - bb->getInstList().push_front(ph); - return true; - } - return false; + // don't revisit nodes + if (visited.count(BB)) return; + + // mark as visited + visited.insert(BB); + + // keep track of the value of each variable we're watching.. how? + for (BasicBlock::iterator II = BB->begin(); II != BB->end(); ++II) { + Instruction *I = *II; //get the instruction + + if (LoadInst *LI = dyn_cast(I)) { + Value *Ptr = LI->getPointerOperand(); + + if (AllocaInst *Src = dyn_cast(Ptr)) { + map::iterator ai = AllocaLookup.find(Src); + if (ai != AllocaLookup.end()) { + Value *V = TOS[ai->second]; + + // walk the use list of this load and replace all uses with r + LI->replaceAllUsesWith(V); + KillList.push_back(LI); // Mark the load to be deleted + } + } + } else if (StoreInst *SI = dyn_cast(I)) { + // delete this instruction and mark the name as the current holder of the + // value + Value *Ptr = SI->getPointerOperand(); + if (AllocaInst *Dest = dyn_cast(Ptr)) { + map::iterator ai = AllocaLookup.find(Dest); + if (ai != AllocaLookup.end()) { + // what value were we writing? + TOS[ai->second] = SI->getOperand(0); + KillList.push_back(SI); // Mark the store to be deleted + } + } + + } else if (TerminatorInst *TI = dyn_cast(I)) { + // Recurse across our successors + for (unsigned i = 0; i != TI->getNumSuccessors(); i++) { + CurrentValue.push_back(CurrentValue.back()); + traverse(TI->getSuccessor(i), BB); // This node becomes the predecessor + CurrentValue.pop_back(); + } + } + } } @@ -314,7 +263,6 @@ namespace { virtual bool runOnFunction(Function *F) { return (bool)PromoteInstance(F, getAnalysis()); } - // getAnalysisUsage - We need dominance frontiers // @@ -328,7 +276,5 @@ namespace { // createPromoteMemoryToRegister - Provide an entry point to create this pass. // Pass *createPromoteMemoryToRegister() { - return new PromotePass(); + return new PromotePass(); } - -