+ SmallVector<AllocaInst*, 16> &RetryList;
+ DominatorTree &DT;
+ DominanceFrontier &DF;
+ const TargetData &TD;
+
+ /// AST - An AliasSetTracker object to update. If null, don't update it.
+ ///
+ AliasSetTracker *AST;
+
+ /// AllocaLookup - Reverse mapping of Allocas.
+ ///
+ std::map<AllocaInst*, unsigned> AllocaLookup;
+
+ /// NewPhiNodes - The PhiNodes we're adding.
+ ///
+ std::map<BasicBlock*, std::vector<PHINode*> > NewPhiNodes;
+
+ /// PointerAllocaValues - If we are updating an AliasSetTracker, then for
+ /// each alloca that is of pointer type, we keep track of what to copyValue
+ /// to the inserted PHI nodes here.
+ ///
+ std::vector<Value*> PointerAllocaValues;
+
+ /// Visited - The set of basic blocks the renamer has already visited.
+ ///
+ std::set<BasicBlock*> Visited;
+
+ /// BBNumbers - Contains a stable numbering of basic blocks to avoid
+ /// non-determinstic behavior.
+ StableBasicBlockNumbering BBNumbers;
+
+ public:
+ PromoteMem2Reg(const std::vector<AllocaInst*> &A,
+ SmallVector<AllocaInst*, 16> &Retry, DominatorTree &dt,
+ DominanceFrontier &df, const TargetData &td,
+ AliasSetTracker *ast)
+ : Allocas(A), RetryList(Retry), DT(dt), DF(df), TD(td), AST(ast) {}
+
+ void run();
+
+ /// properlyDominates - Return true if I1 properly dominates I2.
+ ///
+ bool properlyDominates(Instruction *I1, Instruction *I2) const {
+ if (InvokeInst *II = dyn_cast<InvokeInst>(I1))
+ I1 = II->getNormalDest()->begin();
+ return DT[I1->getParent()]->properlyDominates(DT[I2->getParent()]);
+ }
+
+ /// dominates - Return true if BB1 dominates BB2 using the DominatorTree.
+ ///
+ bool dominates(BasicBlock *BB1, BasicBlock *BB2) const {
+ return DT[BB1]->dominates(DT[BB2]);
+ }
+
+ private:
+ void MarkDominatingPHILive(BasicBlock *BB, unsigned AllocaNum,
+ std::set<PHINode*> &DeadPHINodes);
+ bool PromoteLocallyUsedAlloca(BasicBlock *BB, AllocaInst *AI);
+ void PromoteLocallyUsedAllocas(BasicBlock *BB,
+ const std::vector<AllocaInst*> &AIs);
+
+ void RenamePass(BasicBlock *BB, BasicBlock *Pred,
+ std::vector<Value*> &IncVals);
+ bool QueuePhiNode(BasicBlock *BB, unsigned AllocaIdx, unsigned &Version,
+ std::set<PHINode*> &InsertedPHINodes);
+ };
+} // end of anonymous namespace
+
+void PromoteMem2Reg::run() {
+ Function &F = *DF.getRoot()->getParent();
+
+ // LocallyUsedAllocas - Keep track of all of the alloca instructions which are
+ // only used in a single basic block. These instructions can be efficiently
+ // promoted by performing a single linear scan over that one block. Since
+ // individual basic blocks are sometimes large, we group together all allocas
+ // that are live in a single basic block by the basic block they are live in.
+ std::map<BasicBlock*, std::vector<AllocaInst*> > LocallyUsedAllocas;
+
+ if (AST) PointerAllocaValues.resize(Allocas.size());
+
+ for (unsigned AllocaNum = 0; AllocaNum != Allocas.size(); ++AllocaNum) {
+ AllocaInst *AI = Allocas[AllocaNum];
+
+ assert(isAllocaPromotable(AI, TD) &&
+ "Cannot promote non-promotable alloca!");
+ assert(AI->getParent()->getParent() == &F &&
+ "All allocas should be in the same function, which is same as DF!");
+
+ if (AI->use_empty()) {
+ // If there are no uses of the alloca, just delete it now.
+ if (AST) AST->deleteValue(AI);
+ AI->eraseFromParent();
+
+ // Remove the alloca from the Allocas list, since it has been processed
+ Allocas[AllocaNum] = Allocas.back();
+ Allocas.pop_back();
+ --AllocaNum;
+ continue;
+ }
+
+ // Calculate the set of read and write-locations for each alloca. This is
+ // analogous to finding the 'uses' and 'definitions' of each variable.
+ std::vector<BasicBlock*> DefiningBlocks;
+ std::vector<BasicBlock*> UsingBlocks;
+
+ StoreInst *OnlyStore = 0;
+ BasicBlock *OnlyBlock = 0;
+ bool OnlyUsedInOneBlock = true;
+
+ // 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.
+ Value *AllocaPointerVal = 0;
+ for (Value::use_iterator U =AI->use_begin(), E = AI->use_end(); U != E;++U){
+ Instruction *User = cast<Instruction>(*U);
+ if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
+ // Remember the basic blocks which define new values for the alloca
+ DefiningBlocks.push_back(SI->getParent());
+ AllocaPointerVal = SI->getOperand(0);
+ OnlyStore = SI;
+ } else {
+ LoadInst *LI = cast<LoadInst>(User);
+ // Otherwise it must be a load instruction, keep track of variable reads
+ UsingBlocks.push_back(LI->getParent());
+ AllocaPointerVal = LI;
+ }
+
+ if (OnlyUsedInOneBlock) {
+ if (OnlyBlock == 0)
+ OnlyBlock = User->getParent();
+ else if (OnlyBlock != User->getParent())
+ OnlyUsedInOneBlock = false;
+ }
+ }
+
+ // If the alloca is only read and written in one basic block, just perform a
+ // linear sweep over the block to eliminate it.
+ if (OnlyUsedInOneBlock) {
+ LocallyUsedAllocas[OnlyBlock].push_back(AI);
+
+ // Remove the alloca from the Allocas list, since it will be processed.
+ Allocas[AllocaNum] = Allocas.back();
+ Allocas.pop_back();
+ --AllocaNum;
+ continue;
+ }
+
+ // If there is only a single store to this value, replace any loads of
+ // it that are directly dominated by the definition with the value stored.
+ if (DefiningBlocks.size() == 1) {
+ // Be aware of loads before the store.
+ std::set<BasicBlock*> ProcessedBlocks;
+ for (unsigned i = 0, e = UsingBlocks.size(); i != e; ++i)
+ // If the store dominates the block and if we haven't processed it yet,
+ // do so now.
+ if (dominates(OnlyStore->getParent(), UsingBlocks[i]))
+ if (ProcessedBlocks.insert(UsingBlocks[i]).second) {
+ BasicBlock *UseBlock = UsingBlocks[i];
+
+ // If the use and store are in the same block, do a quick scan to
+ // verify that there are no uses before the store.
+ if (UseBlock == OnlyStore->getParent()) {
+ BasicBlock::iterator I = UseBlock->begin();
+ for (; &*I != OnlyStore; ++I) { // scan block for store.
+ if (isa<LoadInst>(I) && I->getOperand(0) == AI)
+ break;
+ }
+ if (&*I != OnlyStore) break; // Do not handle this case.
+ }
+
+ // Otherwise, if this is a different block or if all uses happen
+ // after the store, do a simple linear scan to replace loads with
+ // the stored value.
+ for (BasicBlock::iterator I = UseBlock->begin(),E = UseBlock->end();
+ I != E; ) {
+ if (LoadInst *LI = dyn_cast<LoadInst>(I++)) {
+ if (LI->getOperand(0) == AI) {
+ LI->replaceAllUsesWith(OnlyStore->getOperand(0));
+ if (AST && isa<PointerType>(LI->getType()))
+ AST->deleteValue(LI);
+ LI->eraseFromParent();
+ }
+ }
+ }
+
+ // Finally, remove this block from the UsingBlock set.
+ UsingBlocks[i] = UsingBlocks.back();
+ --i; --e;
+ }
+
+ // Finally, after the scan, check to see if the store is all that is left.
+ if (UsingBlocks.empty()) {
+ // The alloca has been processed, move on.
+ Allocas[AllocaNum] = Allocas.back();
+ Allocas.pop_back();
+ --AllocaNum;
+ continue;
+ }
+ }
+
+
+ if (AST)
+ PointerAllocaValues[AllocaNum] = AllocaPointerVal;
+
+ // If we haven't computed a numbering for the BB's in the function, do so
+ // now.
+ BBNumbers.compute(F);
+
+ // Compute the locations where PhiNodes need to be inserted. Look at the
+ // dominance frontier of EACH basic-block we have a write in.
+ //
+ unsigned CurrentVersion = 0;
+ std::set<PHINode*> InsertedPHINodes;
+ std::vector<unsigned> DFBlocks;
+ while (!DefiningBlocks.empty()) {
+ BasicBlock *BB = DefiningBlocks.back();
+ DefiningBlocks.pop_back();
+
+ // Look up the DF for this write, add it to PhiNodes
+ DominanceFrontier::const_iterator it = DF.find(BB);
+ if (it != DF.end()) {
+ const DominanceFrontier::DomSetType &S = it->second;
+
+ // In theory we don't need the indirection through the DFBlocks vector.
+ // In practice, the order of calling QueuePhiNode would depend on the
+ // (unspecified) ordering of basic blocks in the dominance frontier,
+ // which would give PHI nodes non-determinstic subscripts. Fix this by
+ // processing blocks in order of the occurance in the function.
+ for (DominanceFrontier::DomSetType::const_iterator P = S.begin(),
+ PE = S.end(); P != PE; ++P)
+ DFBlocks.push_back(BBNumbers.getNumber(*P));
+
+ // Sort by which the block ordering in the function.
+ std::sort(DFBlocks.begin(), DFBlocks.end());
+
+ for (unsigned i = 0, e = DFBlocks.size(); i != e; ++i) {
+ BasicBlock *BB = BBNumbers.getBlock(DFBlocks[i]);
+ if (QueuePhiNode(BB, AllocaNum, CurrentVersion, InsertedPHINodes))
+ DefiningBlocks.push_back(BB);
+ }
+ DFBlocks.clear();
+ }
+ }