From 397d40573170cfd68b0c7f60ff7df0ed535db23d Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Fri, 8 Jun 2007 01:03:01 +0000 Subject: [PATCH] Add partial redundancy elimination. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37510 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/GVNPRE.cpp | 333 +++++++++++++++++++++++-------- 1 file changed, 249 insertions(+), 84 deletions(-) diff --git a/lib/Transforms/Scalar/GVNPRE.cpp b/lib/Transforms/Scalar/GVNPRE.cpp index d6fc21a0387..2336be8901c 100644 --- a/lib/Transforms/Scalar/GVNPRE.cpp +++ b/lib/Transforms/Scalar/GVNPRE.cpp @@ -27,6 +27,7 @@ #include "llvm/Analysis/PostDominators.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Support/CFG.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include @@ -64,6 +65,9 @@ namespace { private: uint32_t nextValueNumber; typedef std::map ValueTable; + ValueTable VN; + std::set MS; + std::set createdExpressions; virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); @@ -73,25 +77,23 @@ namespace { // Helper fuctions // FIXME: eliminate or document these better - void dump(ValueTable& VN, std::set& s); - void dump_unique(ValueTable& VN, std::set& s); - void clean(ValueTable VN, std::set& set); - bool add(ValueTable& VN, std::set& MS, Value* V); - Value* find_leader(std::set& vals, Value* v); - Value* phi_translate(ValueTable& VN, std::set& MS, - std::set& set, + void dump(std::set& s); + void dump_unique(std::set& s); + void clean(std::set& set); + bool add(Value* V, uint32_t number); + Value* find_leader(std::set& vals, + Value* v); + Value* phi_translate(std::set& set, Value* V, BasicBlock* pred); - void phi_translate_set(ValueTable& VN, std::set& MS, - std::set& anticIn, BasicBlock* B, + void phi_translate_set(std::set& anticIn, BasicBlock* B, std::set& out); - void topo_sort(ValueTable& VN, std::set& set, + void topo_sort(std::set& set, std::vector& vec); // For a given block, calculate the generated expressions, temporaries, // and the AVAIL_OUT set - void CalculateAvailOut(ValueTable& VN, std::set& MS, - DomTreeNode* DI, + void CalculateAvailOut(DomTreeNode* DI, std::set& currExps, std::set& currPhis, std::set& currTemps, @@ -111,35 +113,33 @@ RegisterPass X("gvnpre", -bool GVNPRE::add(ValueTable& VN, std::set& MS, Value* V) { - std::pair ret = VN.insert(std::make_pair(V, nextValueNumber)); - if (ret.second) - nextValueNumber++; +bool GVNPRE::add(Value* V, uint32_t number) { + std::pair ret = VN.insert(std::make_pair(V, number)); if (isa(V) || isa(V)) MS.insert(V); return ret.second; } -Value* GVNPRE::find_leader(std::set& vals, - Value* v) { - ExprLT cmp; +Value* GVNPRE::find_leader(std::set& vals, Value* v) { for (std::set::iterator I = vals.begin(), E = vals.end(); - I != E; ++I) - if (!cmp(v, *I) && !cmp(*I, v)) + I != E; ++I) { + assert(VN.find(v) != VN.end() && "Value not numbered?"); + assert(VN.find(*I) != VN.end() && "Value not numbered?"); + if (VN[v] == VN[*I]) return *I; + } return 0; } -Value* GVNPRE::phi_translate(ValueTable& VN, std::set& MS, - std::set& set, +Value* GVNPRE::phi_translate(std::set& set, Value* V, BasicBlock* pred) { if (V == 0) return 0; if (BinaryOperator* BO = dyn_cast(V)) { Value* newOp1 = isa(BO->getOperand(0)) - ? phi_translate(VN, MS, set, + ? phi_translate(set, find_leader(set, BO->getOperand(0)), pred) : BO->getOperand(0); @@ -147,7 +147,7 @@ Value* GVNPRE::phi_translate(ValueTable& VN, std::set& MS, return 0; Value* newOp2 = isa(BO->getOperand(1)) - ? phi_translate(VN, MS, set, + ? phi_translate(set, find_leader(set, BO->getOperand(1)), pred) : BO->getOperand(1); @@ -155,12 +155,14 @@ Value* GVNPRE::phi_translate(ValueTable& VN, std::set& MS, return 0; if (newOp1 != BO->getOperand(0) || newOp2 != BO->getOperand(1)) { - Value* newVal = BinaryOperator::create(BO->getOpcode(), + Instruction* newVal = BinaryOperator::create(BO->getOpcode(), newOp1, newOp2, BO->getName()+".gvnpre"); - + if (add(newVal, nextValueNumber)) + nextValueNumber++; if (!find_leader(set, newVal)) { - add(VN, MS, newVal); + DOUT << "Creating value: " << std::hex << newVal << std::dec << "\n"; + createdExpressions.insert(newVal); return newVal; } else { delete newVal; @@ -175,39 +177,42 @@ Value* GVNPRE::phi_translate(ValueTable& VN, std::set& MS, return V; } -void GVNPRE::phi_translate_set(GVNPRE::ValueTable& VN, - std::set& MS, - std::set& anticIn, BasicBlock* B, +void GVNPRE::phi_translate_set(std::set& anticIn, BasicBlock* B, std::set& out) { for (std::set::iterator I = anticIn.begin(), E = anticIn.end(); I != E; ++I) { - Value* V = phi_translate(VN, MS, anticIn, *I, B); + Value* V = phi_translate(anticIn, *I, B); if (V != 0) out.insert(V); } } // Remove all expressions whose operands are not themselves in the set -void GVNPRE::clean(GVNPRE::ValueTable VN, std::set& set) { +void GVNPRE::clean(std::set& set) { std::vector worklist; - topo_sort(VN, set, worklist); + topo_sort(set, worklist); - while (!worklist.empty()) { - Value* v = worklist.back(); - worklist.pop_back(); + for (unsigned i = 0; i < worklist.size(); ++i) { + Value* v = worklist[i]; if (BinaryOperator* BO = dyn_cast(v)) { - bool lhsValid = false; - for (std::set::iterator I = set.begin(), E = set.end(); - I != E; ++I) - if (VN[*I] == VN[BO->getOperand(0)]); - lhsValid = true; + bool lhsValid = !isa(BO->getOperand(0)); + if (!lhsValid) + for (std::set::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN[*I] == VN[BO->getOperand(0)]) { + lhsValid = true; + break; + } - bool rhsValid = false; + bool rhsValid = !isa(BO->getOperand(1)); + if (!rhsValid) for (std::set::iterator I = set.begin(), E = set.end(); I != E; ++I) - if (VN[*I] == VN[BO->getOperand(1)]); + if (VN[*I] == VN[BO->getOperand(1)]) { rhsValid = true; + break; + } if (!lhsValid || !rhsValid) set.erase(BO); @@ -215,25 +220,26 @@ void GVNPRE::clean(GVNPRE::ValueTable VN, std::set& set) { } } -void GVNPRE::topo_sort(GVNPRE::ValueTable& VN, - std::set& set, +void GVNPRE::topo_sort(std::set& set, std::vector& vec) { - std::set toErase; + std::set toErase; for (std::set::iterator I = set.begin(), E = set.end(); I != E; ++I) { if (BinaryOperator* BO = dyn_cast(*I)) for (std::set::iterator SI = set.begin(); SI != E; ++SI) { - if (VN[BO->getOperand(0)] == VN[*SI] || VN[BO->getOperand(1)] == VN[*SI]) { - toErase.insert(BO); + if (VN[BO->getOperand(0)] == VN[*SI] || + VN[BO->getOperand(1)] == VN[*SI]) { + toErase.insert(*SI); } } } std::vector Q; - std::insert_iterator > q_ins(Q, Q.begin()); - std::set_difference(set.begin(), set.end(), - toErase.begin(), toErase.end(), - q_ins); + for (std::set::iterator I = set.begin(), E = set.end(); + I != E; ++I) { + if (toErase.find(*I) == toErase.end()) + Q.push_back(*I); + } std::set visited; while (!Q.empty()) { @@ -263,7 +269,7 @@ void GVNPRE::topo_sort(GVNPRE::ValueTable& VN, } -void GVNPRE::dump(GVNPRE::ValueTable& VN, std::set& s) { +void GVNPRE::dump(std::set& s) { DOUT << "{ "; for (std::set::iterator I = s.begin(), E = s.end(); I != E; ++I) { @@ -272,7 +278,7 @@ void GVNPRE::dump(GVNPRE::ValueTable& VN, std::set& s) { DOUT << "}\n\n"; } -void GVNPRE::dump_unique(GVNPRE::ValueTable& VN, std::set& s) { +void GVNPRE::dump_unique(std::set& s) { DOUT << "{ "; for (std::set::iterator I = s.begin(), E = s.end(); I != E; ++I) { @@ -281,8 +287,7 @@ void GVNPRE::dump_unique(GVNPRE::ValueTable& VN, std::set& s) { DOUT << "}\n\n"; } -void GVNPRE::CalculateAvailOut(GVNPRE::ValueTable& VN, std::set& MS, - DomTreeNode* DI, +void GVNPRE::CalculateAvailOut(DomTreeNode* DI, std::set& currExps, std::set& currPhis, std::set& currTemps, @@ -302,7 +307,8 @@ void GVNPRE::CalculateAvailOut(GVNPRE::ValueTable& VN, std::set& // Handle PHI nodes... if (PHINode* p = dyn_cast(BI)) { - add(VN, MS, p); + if (add(p, nextValueNumber)) + nextValueNumber++; currPhis.insert(p); // Handle binary ops... @@ -310,7 +316,8 @@ void GVNPRE::CalculateAvailOut(GVNPRE::ValueTable& VN, std::set& Value* leftValue = BO->getOperand(0); Value* rightValue = BO->getOperand(1); - add(VN, MS, BO); + if (add(BO, nextValueNumber)) + nextValueNumber++; if (isa(leftValue)) currExps.insert(leftValue); @@ -320,7 +327,8 @@ void GVNPRE::CalculateAvailOut(GVNPRE::ValueTable& VN, std::set& // Handle unsupported ops } else if (!BI->isTerminator()){ - add(VN, MS, BI); + if (add(BI, nextValueNumber)) + nextValueNumber++; currTemps.insert(BI); } @@ -330,8 +338,9 @@ void GVNPRE::CalculateAvailOut(GVNPRE::ValueTable& VN, std::set& } bool GVNPRE::runOnFunction(Function &F) { - ValueTable VN; - std::set maximalSet; + VN.clear(); + MS.clear(); + createdExpressions.clear(); std::map > generatedExpressions; std::map > generatedPhis; @@ -355,12 +364,12 @@ bool GVNPRE::runOnFunction(Function &F) { std::set& currTemps = generatedTemporaries[DI->getBlock()]; std::set& currAvail = availableOut[DI->getBlock()]; - CalculateAvailOut(VN, maximalSet, *DI, currExps, currPhis, + CalculateAvailOut(*DI, currExps, currPhis, currTemps, currAvail, availableOut); } DOUT << "Maximal Set: "; - dump_unique(VN, maximalSet); + dump_unique(MS); DOUT << "\n"; PostDominatorTree &PDT = getAnalysis(); @@ -377,16 +386,16 @@ bool GVNPRE::runOnFunction(Function &F) { // Top-down walk of the postdominator tree for (df_iterator PDI = - df_begin(PDT.getRootNode()), E = df_end(DT.getRootNode()); + df_begin(PDT.getRootNode()), E = df_end(PDT.getRootNode()); PDI != E; ++PDI) { BasicBlock* BB = PDI->getBlock(); DOUT << "Block: " << BB->getName() << "\n"; DOUT << "TMP_GEN: "; - dump(VN, generatedTemporaries[BB]); + dump(generatedTemporaries[BB]); DOUT << "\n"; DOUT << "EXP_GEN: "; - dump_unique(VN, generatedExpressions[BB]); + dump_unique(generatedExpressions[BB]); visited.insert(BB); std::set& anticIn = anticipatedIn[BB]; @@ -395,9 +404,9 @@ bool GVNPRE::runOnFunction(Function &F) { if (BB->getTerminator()->getNumSuccessors() == 1) { if (visited.find(BB->getTerminator()->getSuccessor(0)) == visited.end()) - phi_translate_set(VN, maximalSet, maximalSet, BB, anticOut); + phi_translate_set(MS, BB, anticOut); else - phi_translate_set(VN, maximalSet, + phi_translate_set( anticipatedIn[BB->getTerminator()->getSuccessor(0)], BB, anticOut); } else if (BB->getTerminator()->getNumSuccessors() > 1) { BasicBlock* first = BB->getTerminator()->getSuccessor(0); @@ -420,7 +429,7 @@ bool GVNPRE::runOnFunction(Function &F) { } DOUT << "ANTIC_OUT: "; - dump_unique(VN, anticOut); + dump_unique(anticOut); DOUT << "\n"; std::set S; @@ -438,10 +447,10 @@ bool GVNPRE::runOnFunction(Function &F) { anticIn.insert(*I); } - clean(VN, anticIn); + clean(anticIn); DOUT << "ANTIC_IN: "; - dump_unique(VN, anticIn); + dump_unique(anticIn); DOUT << "\n"; if (old.size() != anticIn.size()) @@ -459,25 +468,173 @@ bool GVNPRE::runOnFunction(Function &F) { DOUT << "Name: " << I->getName().c_str() << "\n"; DOUT << "TMP_GEN: "; - dump(VN, generatedTemporaries[I]); + dump(generatedTemporaries[I]); DOUT << "\n"; DOUT << "EXP_GEN: "; - dump_unique(VN, generatedExpressions[I]); + dump_unique(generatedExpressions[I]); DOUT << "\n"; DOUT << "ANTIC_IN: "; - dump_unique(VN, anticipatedIn[I]); + dump_unique(anticipatedIn[I]); DOUT << "\n"; DOUT << "AVAIL_OUT: "; - dump_unique(VN, availableOut[I]); + dump_unique(availableOut[I]); DOUT << "\n"; } // Phase 2: Insert - // FIXME: Not implemented yet + + DOUT<< "\nPhase 2: Insertion\n"; + + std::map > new_sets; + unsigned i_iterations = 0; + bool new_stuff = true; + while (new_stuff) { + new_stuff = false; + DOUT << "Iteration: " << i_iterations << "\n\n"; + for (df_iterator DI = df_begin(DT.getRootNode()), + E = df_end(DT.getRootNode()); DI != E; ++DI) { + BasicBlock* BB = DI->getBlock(); + + std::set& new_set = new_sets[BB]; + std::set& availOut = availableOut[BB]; + std::set& anticIn = anticipatedIn[BB]; + + // Replace leaders with leaders inherited from dominator + if (DI->getIDom() != 0) { + std::set& dom_set = new_sets[DI->getIDom()->getBlock()]; + for (std::set::iterator I = dom_set.begin(), + E = dom_set.end(); I != E; ++I) { + new_set.insert(*I); + + std::set::iterator val = availOut.find(*I); + if (val != availOut.end()) + new_set.erase(val); + new_set.insert(*I); + } + } + + // If there is more than one predecessor... + if (pred_begin(BB) != pred_end(BB) && ++pred_begin(BB) != pred_end(BB)) { + std::vector workList; + topo_sort(anticIn, workList); + + DOUT << "Merge Block: " << BB->getName() << "\n"; + DOUT << "ANTIC_IN: "; + dump_unique(anticIn); + DOUT << "\n"; + + while (!workList.empty()) { + Value* e = workList.back(); + workList.pop_back(); + + if (isa(e)) { + if (find_leader(availableOut[DI->getIDom()->getBlock()], e) != 0) + continue; + + std::map avail; + bool by_some = false; + int num_avail = 0; + + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); PI != PE; + ++PI) { + Value *e2 = phi_translate(anticIn, e, *PI); + Value *e3 = find_leader(availableOut[*PI], e2); + + if (e3 == 0) { + std::map::iterator av = avail.find(*PI); + if (av != avail.end()) + avail.erase(av); + avail.insert(std::make_pair(*PI, e2)); + } else { + std::map::iterator av = avail.find(*PI); + if (av != avail.end()) + avail.erase(av); + avail.insert(std::make_pair(*PI, e3)); + + by_some = true; + num_avail++; + } + } + + if (by_some && + num_avail < std::distance(pred_begin(BB), pred_end(BB))) { + DOUT << "Processing Value: "; + DEBUG(e->dump()); + DOUT << "\n\n"; + + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + PI != PE; ++PI) { + Value* e2 = avail[*PI]; + if (!find_leader(availableOut[*PI], e2)) { + BinaryOperator* BO = cast(e2); + + Value* s1 = 0; + if (isa(BO->getOperand(0))) + s1 = find_leader(availableOut[*PI], BO->getOperand(0)); + else + s1 = BO->getOperand(0); + + Value* s2 = 0; + if (isa(BO->getOperand(1))) + s2 = find_leader(availableOut[*PI], BO->getOperand(1)); + else + s2 = BO->getOperand(1); + + Value* newVal = BinaryOperator::create(BO->getOpcode(), + s1, s2, + BO->getName()+".gvnpre", + (*PI)->getTerminator()); + add(newVal, VN[BO]); + availableOut[*PI].insert(newVal); + + DOUT << "Creating value: " << std::hex << newVal << std::dec << "\n"; + + std::map::iterator av = avail.find(*PI); + if (av != avail.end()) + avail.erase(av); + avail.insert(std::make_pair(*PI, newVal)); + } + } + + PHINode* p = 0; + + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + PI != PE; ++PI) { + if (p == 0) + p = new PHINode(avail[*PI]->getType(), "gvnpre-join", + BB->begin()); + + p->addIncoming(avail[*PI], *PI); + } + + add(p, VN[e]); + DOUT << "Creating value: " << std::hex << p << std::dec << "\n"; + + availOut.insert(p); + new_stuff = true; + + DOUT << "Preds After Processing: "; + for (pred_iterator PI = pred_begin(BB), PE = pred_end(BB); + PI != PE; ++PI) + DEBUG((*PI)->dump()); + DOUT << "\n\n"; + + DOUT << "Merge Block After Processing: "; + DEBUG(BB->dump()); + DOUT << "\n\n"; + + new_set.insert(p); + } + } + } + } + } + i_iterations++; + } // Phase 3: Eliminate for (df_iterator DI = df_begin(DT.getRootNode()), @@ -488,13 +645,15 @@ bool GVNPRE::runOnFunction(Function &F) { for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI) { - Value* leader = find_leader(availableOut[BB], BI); - if (leader != 0) - if (Instruction* Instr = dyn_cast(leader)) - if (Instr->getParent() != 0 && Instr != BI) { - BI->replaceAllUsesWith(leader); - erase.push_back(BI); - } + if (!BI->isTerminator()) { + Value* leader = find_leader(availableOut[BB], BI); + if (leader != 0) + if (Instruction* Instr = dyn_cast(leader)) + if (Instr->getParent() != 0 && Instr != BI) { + BI->replaceAllUsesWith(leader); + erase.push_back(BI); + } + } } for (std::vector::iterator I = erase.begin(), E = erase.end(); @@ -502,5 +661,11 @@ bool GVNPRE::runOnFunction(Function &F) { (*I)->eraseFromParent(); } + // Phase 4: Cleanup + for (std::set::iterator I = createdExpressions.begin(), + E = createdExpressions.end(); I != E; ++I) { + delete *I; + } + return false; }