X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTransforms%2FScalar%2FGVN.cpp;h=5564dbde1bfb311849d0648a87cf488780cc1adf;hb=2e9f0b1a323848f6d548c1e9eb16ece6a3881dbd;hp=cbc24eda56fe00c7f516cd40ef153ffa0f534162;hpb=5c274eebc6b5444db123028f29b7491763c08585;p=oota-llvm.git diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index cbc24eda56f..5564dbde1bf 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -32,6 +32,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/MemoryDependenceAnalysis.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" @@ -41,6 +42,9 @@ STATISTIC(NumGVNInstr, "Number of instructions deleted"); STATISTIC(NumGVNLoad, "Number of loads deleted"); STATISTIC(NumGVNPRE, "Number of instructions PRE'd"); +static cl::opt EnablePRE("enable-pre", + cl::init(false), cl::Hidden); + //===----------------------------------------------------------------------===// // ValueTable Class //===----------------------------------------------------------------------===// @@ -688,6 +692,15 @@ namespace llvm { }; } +namespace { + struct VISIBILITY_HIDDEN ValueNumberScope { + ValueNumberScope* parent; + DenseMap table; + + ValueNumberScope(ValueNumberScope* p) : parent(p) { } + }; +} + namespace { class VISIBILITY_HIDDEN GVN : public FunctionPass { @@ -698,7 +711,7 @@ namespace { private: ValueTable VN; - DenseMap > localAvail; + DenseMap localAvail; typedef DenseMap > PhiMapType; PhiMapType phiMap; @@ -706,10 +719,11 @@ namespace { // This transformation requires dominator postdominator info virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); AU.addRequired(); AU.addRequired(); AU.addRequired(); + + AU.addPreserved(); AU.addPreserved(); AU.addPreserved(); } @@ -733,6 +747,7 @@ namespace { Value* CollapsePhi(PHINode* p); bool isSafeReplacement(PHINode* p, Instruction* inst); bool performPRE(Function& F); + Value* lookupNumber(BasicBlock* BB, uint32_t num); }; char GVN::ID = 0; @@ -1004,6 +1019,24 @@ bool GVN::processLoad(LoadInst *L, DenseMap &lastLoad, return deletedLoad; } +Value* GVN::lookupNumber(BasicBlock* BB, uint32_t num) { + DenseMap::iterator I = localAvail.find(BB); + if (I == localAvail.end()) + return 0; + + ValueNumberScope* locals = I->second; + + while (locals) { + DenseMap::iterator I = locals->table.find(num); + if (I != locals->table.end()) + return I->second; + else + locals = locals->parent; + } + + return 0; +} + /// processInstruction - When calculating availability, handle an instruction /// by inserting it into the appropriate sets bool GVN::processInstruction(Instruction *I, @@ -1014,7 +1047,7 @@ bool GVN::processInstruction(Instruction *I, if (!changed) { unsigned num = VN.lookup_or_add(L); - localAvail[I->getParent()].insert(std::make_pair(num, L)); + localAvail[I->getParent()]->table.insert(std::make_pair(num, L)); } return changed; @@ -1025,7 +1058,7 @@ bool GVN::processInstruction(Instruction *I, // Allocations are always uniquely numbered, so we can save time and memory // by fast failing them. if (isa(I)) { - localAvail[I->getParent()].insert(std::make_pair(num, I)); + localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); return false; } @@ -1042,12 +1075,10 @@ bool GVN::processInstruction(Instruction *I, p->replaceAllUsesWith(constVal); toErase.push_back(p); } else { - localAvail[I->getParent()].insert(std::make_pair(num, I)); + localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); } // Perform value-number based elimination - } else if (localAvail[I->getParent()].count(num)) { - Value* repl = localAvail[I->getParent()][num]; - + } else if (Value* repl = lookupNumber(I->getParent(), num)) { // Remove it! MemoryDependenceAnalysis& MD = getAnalysis(); MD.removeInstruction(I); @@ -1057,7 +1088,7 @@ bool GVN::processInstruction(Instruction *I, toErase.push_back(I); return true; } else if (!I->isTerminator()) { - localAvail[I->getParent()].insert(std::make_pair(num, I)); + localAvail[I->getParent()]->table.insert(std::make_pair(num, I)); } return false; @@ -1091,8 +1122,10 @@ bool GVN::processBlock(DomTreeNode* DTN) { bool changed_function = false; if (DTN->getIDom()) - localAvail.insert(std::make_pair(BB, - localAvail[DTN->getIDom()->getBlock()])); + localAvail[BB] = + new ValueNumberScope(localAvail[DTN->getIDom()->getBlock()]); + else + localAvail[BB] = new ValueNumberScope(0); for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE;) { @@ -1139,9 +1172,9 @@ bool GVN::performPRE(Function& F) { for (BasicBlock::iterator BI = CurrentBlock->begin(), BE = CurrentBlock->end(); BI != BE; ) { - if (isa(BI) || isa(BI) || - isa(BI) || isa(BI) || - isa(BI) || isa(BI)) { + if (isa(BI) || isa(BI) || + isa(BI) || BI->mayReadFromMemory() || + BI->mayWriteToMemory()) { BI++; continue; } @@ -1157,19 +1190,29 @@ bool GVN::performPRE(Function& F) { unsigned numWith = 0; unsigned numWithout = 0; BasicBlock* PREPred = 0; + DenseMap predMap; for (pred_iterator PI = pred_begin(CurrentBlock), PE = pred_end(CurrentBlock); PI != PE; ++PI) { // We're not interested in PRE where the block is its - // own predecessor. - if (*PI == CurrentBlock) + // own predecessor, on in blocks with predecessors + // that are not reachable. + if (*PI == CurrentBlock) { + numWithout = 2; + break; + } else if (!localAvail.count(*PI)) { numWithout = 2; - - if (!localAvail[*PI].count(valno)) { + break; + } + + DenseMap::iterator predV = + localAvail[*PI]->table.find(valno); + if (predV == localAvail[*PI]->table.end()) { PREPred = *PI; numWithout++; - } else if (localAvail[*PI][valno] == BI) { + } else if (predV->second == BI) { numWithout = 2; } else { + predMap[*PI] = predV->second; numWith++; } } @@ -1210,11 +1253,11 @@ bool GVN::performPRE(Function& F) { Value* op = BI->getOperand(i); if (isa(op) || isa(op) || isa(op)) PREInstr->setOperand(i, op); - else if (!localAvail[PREPred].count(VN.lookup(op))) { + else if (!lookupNumber(PREPred, VN.lookup(op))) { success = false; break; } else - PREInstr->setOperand(i, localAvail[PREPred][VN.lookup(op)]); + PREInstr->setOperand(i, lookupNumber(PREPred, VN.lookup(op))); } // Fail out if we encounter an operand that is not available in @@ -1228,11 +1271,12 @@ bool GVN::performPRE(Function& F) { PREInstr->insertBefore(PREPred->getTerminator()); PREInstr->setName(BI->getName() + ".pre"); + predMap[PREPred] = PREInstr; VN.add(PREInstr, valno); NumGVNPRE++; // Update the availability map to include the new instruction. - localAvail[PREPred].insert(std::make_pair(valno, PREInstr)); + localAvail[PREPred]->table.insert(std::make_pair(valno, PREInstr)); // Create a PHI to make the value available in this block. PHINode* Phi = PHINode::Create(BI->getType(), @@ -1240,18 +1284,10 @@ bool GVN::performPRE(Function& F) { CurrentBlock->begin()); for (pred_iterator PI = pred_begin(CurrentBlock), PE = pred_end(CurrentBlock); PI != PE; ++PI) - Phi->addIncoming(localAvail[*PI][valno], *PI); + Phi->addIncoming(predMap[*PI], *PI); VN.add(Phi, valno); - - // The newly created PHI completely replaces the old instruction, - // so we need to update the maps to reflect this. - for (DenseMap >::iterator - UI = localAvail.begin(), UE = localAvail.end(); UI != UE; ++UI) - for (DenseMap::iterator UUI = UI->second.begin(), - UUE = UI->second.end(); UUI != UUE; ++UUI) - if (UUI->second == BI) - UUI->second = Phi; + localAvail[CurrentBlock]->table[valno] = Phi; BI->replaceAllUsesWith(Phi); VN.erase(BI); @@ -1275,9 +1311,13 @@ bool GVN::performPRE(Function& F) { bool GVN::iterateOnFunction(Function &F) { // Clean out global sets from any previous functions VN.clear(); - localAvail.clear(); phiMap.clear(); + for (DenseMap::iterator + I = localAvail.begin(), E = localAvail.end(); I != E; ++I) + delete I->second; + localAvail.clear(); + DominatorTree &DT = getAnalysis(); // Top-down walk of the dominator tree @@ -1285,7 +1325,9 @@ bool GVN::iterateOnFunction(Function &F) { for (df_iterator DI = df_begin(DT.getRootNode()), DE = df_end(DT.getRootNode()); DI != DE; ++DI) changed |= processBlock(*DI); - - changed |= performPRE(F); + + if (EnablePRE) + changed |= performPRE(F); + return changed; }