diff --git a/lib/Transforms/Scalar/GVNPRE.cpp b/lib/Transforms/Scalar/GVNPRE.cpp index 4f5205434df..4b27342c3ed 100644 --- a/lib/Transforms/Scalar/GVNPRE.cpp +++ b/lib/Transforms/Scalar/GVNPRE.cpp @@ -36,6 +36,23 @@ #include using namespace llvm; +struct ExprLT { + bool operator()(Value* left, Value* right) { + if (!isa(left) || !isa(right)) + return left < right; + + BinaryOperator* BO1 = cast(left); + BinaryOperator* BO2 = cast(right); + + if ((*this)(BO1->getOperand(0), BO2->getOperand(0))) + return true; + else if ((*this)(BO2->getOperand(0), BO1->getOperand(0))) + return false; + else + return (*this)(BO1->getOperand(1), BO2->getOperand(1)); + } +}; + namespace { class VISIBILITY_HIDDEN GVNPRE : public FunctionPass { @@ -46,49 +63,7 @@ namespace { private: uint32_t nextValueNumber; - - struct Expression { - char opcode; - Value* value; - uint32_t lhs; - uint32_t rhs; - - bool operator<(const Expression& other) const { - if (opcode < other.opcode) - return true; - else if (other.opcode < opcode) - return false; - - if (opcode == 0) { - return value < other.value; - } else { - if (lhs < other.lhs) - return true; - else if (other.lhs < lhs) - return false; - else - return rhs < other.rhs; - } - } - - bool operator==(const Expression& other) const { - if (opcode != other.opcode) - return false; - - if (value != other.value) - return false; - - if (lhs != other.lhs) - return false; - - if (rhs != other.rhs) - return false; - - return true; - } - }; - - typedef std::map ValueTable; + typedef std::map ValueTable; virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesCFG(); @@ -98,30 +73,27 @@ namespace { // Helper fuctions // FIXME: eliminate or document these better - void dump(ValueTable& VN, std::set& s); - void clean(ValueTable VN, std::set& set); - Expression add(ValueTable& VN, std::set& MS, Instruction* V); + void dump(ValueTable& VN, std::set& s); + void clean(ValueTable VN, std::set& set); + bool add(ValueTable& VN, std::set& MS, Value* V); ValueTable::iterator lookup(ValueTable& VN, Value* V); - Expression buildExpression(ValueTable& VN, Value* V); - std::set::iterator find_leader(ValueTable VN, - std::set& vals, - uint32_t v); - void phi_translate(ValueTable& VN, std::set& MS, - std::set& anticIn, BasicBlock* B, - std::set& out); + Value* find_leader(ValueTable VN, std::set& vals, uint32_t v); + void phi_translate(ValueTable& VN, std::set& MS, + std::set& anticIn, BasicBlock* B, + std::set& out); - void topo_sort(ValueTable& VN, std::set& set, - std::vector& vec); + void topo_sort(ValueTable& VN, 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, + void CalculateAvailOut(ValueTable& VN, std::set& MS, DominatorTree::Node* DI, - std::set& currExps, + std::set& currExps, std::set& currPhis, - std::set& currTemps, - std::set& currAvail, - std::map > availOut); + std::set& currTemps, + std::set& currAvail, + std::map > availOut); }; @@ -134,269 +106,173 @@ FunctionPass *llvm::createGVNPREPass() { return new GVNPRE(); } RegisterPass X("gvnpre", "Global Value Numbering/Partial Redundancy Elimination"); -// Given a Value, build an Expression to represent it -GVNPRE::Expression GVNPRE::buildExpression(ValueTable& VN, Value* V) { - if (Instruction* I = dyn_cast(V)) { - Expression e; - - switch (I->getOpcode()) { - case 7: - e.opcode = 1; // ADD - break; - case 8: - e.opcode = 2; // SUB - break; - case 9: - e.opcode = 3; // MUL - break; - case 10: - e.opcode = 4; // UDIV - break; - case 11: - e.opcode = 5; // SDIV - break; - case 12: - e.opcode = 6; // FDIV - break; - case 13: - e.opcode = 7; // UREM - break; - case 14: - e.opcode = 8; // SREM - break; - case 15: - e.opcode = 9; // FREM - break; - default: - e.opcode = 0; // OPAQUE - e.lhs = 0; - e.rhs = 0; - e.value = V; - return e; - } - - e.value = 0; - - ValueTable::iterator lhs = lookup(VN, I->getOperand(0)); - if (lhs == VN.end()) { - Expression lhsExp = buildExpression(VN, I->getOperand(0)); - VN.insert(std::make_pair(lhsExp, nextValueNumber)); - e.lhs = nextValueNumber; - nextValueNumber++; - } else - e.lhs = lhs->second; - ValueTable::iterator rhs = lookup(VN, I->getOperand(1)); - if (rhs == VN.end()) { - Expression rhsExp = buildExpression(VN, I->getOperand(1)); - VN.insert(std::make_pair(rhsExp, nextValueNumber)); - e.rhs = nextValueNumber; - nextValueNumber++; - } else - e.rhs = rhs->second; - - return e; - } else { - Expression e; - e.opcode = 0; - e.value = V; - e.lhs = 0; - e.rhs = 0; - - return e; - } -} -GVNPRE::Expression GVNPRE::add(ValueTable& VN, std::set& MS, - Instruction* V) { - Expression e = buildExpression(VN, V); - std::pair ret = VN.insert(std::make_pair(e, nextValueNumber)); + +bool GVNPRE::add(ValueTable& VN, std::set& MS, Value* V) { + std::pair ret = VN.insert(std::make_pair(V, nextValueNumber)); if (ret.second) nextValueNumber++; - if (e.opcode != 0 || (e.opcode == 0 && isa(e.value))) - MS.insert(e); - return e; + if (isa(V) || isa(V)) + MS.insert(V); + return ret.second; } GVNPRE::ValueTable::iterator GVNPRE::lookup(ValueTable& VN, Value* V) { - Expression e = buildExpression(VN, V); - return VN.find(e); + return VN.find(V); } -std::set::iterator GVNPRE::find_leader(GVNPRE::ValueTable VN, - std::set& vals, +Value* GVNPRE::find_leader(GVNPRE::ValueTable VN, + std::set& vals, uint32_t v) { - for (std::set::iterator I = vals.begin(), E = vals.end(); + for (std::set::iterator I = vals.begin(), E = vals.end(); I != E; ++I) if (VN[*I] == v) - return I; + return *I; - return vals.end(); + return 0; } void GVNPRE::phi_translate(GVNPRE::ValueTable& VN, - std::set& MS, - std::set& anticIn, BasicBlock* B, - std::set& out) { + std::set& MS, + std::set& anticIn, BasicBlock* B, + std::set& out) { BasicBlock* succ = B->getTerminator()->getSuccessor(0); - for (std::set::iterator I = anticIn.begin(), E = anticIn.end(); + for (std::set::iterator I = anticIn.begin(), E = anticIn.end(); I != E; ++I) { - if (I->opcode == 0) { - Value *v = I->value; - if (PHINode* p = dyn_cast(v)) { + if (!isa(*I)) { + if (PHINode* p = dyn_cast(*I)) { if (p->getParent() == succ) - out.insert(buildExpression(VN, p->getIncomingValueForBlock(B))); + out.insert(p); } else { out.insert(*I); } } else { - std::set::iterator lhs_it = find_leader(VN, anticIn, I->lhs); - if (lhs_it == anticIn.end()) + BinaryOperator* BO = cast(*I); + Value* lhs = find_leader(VN, anticIn, VN[BO->getOperand(0)]); + if (lhs == 0) continue; - Expression lhs = *lhs_it; - if (lhs.value != 0) - if (PHINode* p = dyn_cast(lhs.value)) - if (p->getParent() == succ) { - Expression t = buildExpression(VN, p->getIncomingValueForBlock(B)); - lhs.opcode = t.opcode; - lhs.value = t.value; - lhs.lhs = t.lhs; - lhs.rhs = t.rhs; - - out.insert(t); - } + if (PHINode* p = dyn_cast(lhs)) + if (p->getParent() == succ) { + lhs = p->getIncomingValueForBlock(B); + out.insert(lhs); + } - std::set::iterator rhs_it = find_leader(VN, anticIn, I->rhs); - if (rhs_it == anticIn.end()) + Value* rhs = find_leader(VN, anticIn, VN[BO->getOperand(1)]); + if (rhs == 0) continue; - Expression rhs = *rhs_it; - if (rhs.value != 0) - if (PHINode* p = dyn_cast(rhs.value)) - if (p->getParent() == succ) { - Expression t = buildExpression(VN, p->getIncomingValueForBlock(B)); - rhs.opcode = t.opcode; - rhs.value = t.value; - rhs.lhs = t.lhs; - rhs.rhs = t.rhs; - - out.insert(t); - } + if (PHINode* p = dyn_cast(rhs)) + if (p->getParent() == succ) { + rhs = p->getIncomingValueForBlock(B); + out.insert(rhs); + } - Expression e; - e.opcode = I->opcode; - e.value = 0; - e.lhs = VN[lhs]; - e.rhs = VN[rhs]; + if (lhs != BO->getOperand(0) || rhs != BO->getOperand(1)) { + BO = BinaryOperator::create(BO->getOpcode(), lhs, rhs, BO->getName()+".gvnpre"); + if (VN.insert(std::make_pair(BO, nextValueNumber)).second) + nextValueNumber++; + MS.insert(BO); + } + + out.insert(BO); - if (VN.insert(std::make_pair(e, nextValueNumber)).second) - nextValueNumber++; - MS.insert(e); } } } // Remove all expressions whose operands are not themselves in the set -void GVNPRE::clean(GVNPRE::ValueTable VN, std::set& set) { - std::vector worklist; +void GVNPRE::clean(GVNPRE::ValueTable VN, std::set& set) { + std::vector worklist; topo_sort(VN, set, worklist); while (!worklist.empty()) { - Expression e = worklist.back(); + Value* v = worklist.back(); worklist.pop_back(); - if (e.opcode == 0) // OPAQUE - continue; + 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 rhsValid = false; + for (std::set::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN[*I] == VN[BO->getOperand(1)]); + rhsValid = true; - bool lhsValid = false; - for (std::set::iterator I = set.begin(), E = set.end(); - I != E; ++I) - if (VN[*I] == e.lhs); - lhsValid = true; - - bool rhsValid = false; - for (std::set::iterator I = set.begin(), E = set.end(); - I != E; ++I) - if (VN[*I] == e.rhs); - rhsValid = true; - - if (!lhsValid || !rhsValid) - set.erase(e); + if (!lhsValid || !rhsValid) + set.erase(BO); + } } } void GVNPRE::topo_sort(GVNPRE::ValueTable& VN, - std::set& set, - std::vector& vec) { - std::set toErase; - for (std::set::iterator I = set.begin(), E = set.end(); + std::set& set, + std::vector& vec) { + std::set toErase; + for (std::set::iterator I = set.begin(), E = set.end(); I != E; ++I) { - for (std::set::iterator SI = set.begin(); SI != E; ++SI) { - if (I->lhs == VN[*SI] || I->rhs == VN[*SI]) { - toErase.insert(*SI); - } + 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); + } } } - std::vector Q; - std::insert_iterator > q_ins(Q, Q.begin()); + std::vector Q; + std::insert_iterator > q_ins(Q, Q.begin()); std::set_difference(set.begin(), set.end(), toErase.begin(), toErase.end(), - q_ins); + q_ins, ExprLT()); - std::set visited; + std::set visited; while (!Q.empty()) { - Expression e = Q.back(); - - if (e.opcode == 0) { + Value* e = Q.back(); + + if (BinaryOperator* BO = dyn_cast(e)) { + Value* l = find_leader(VN, set, VN[BO->getOperand(0)]); + Value* r = find_leader(VN, set, VN[BO->getOperand(1)]); + + if (l != 0 && visited.find(l) == visited.end()) + Q.push_back(l); + else if (r != 0 && visited.find(r) == visited.end()) + Q.push_back(r); + else { + vec.push_back(e); + visited.insert(e); + Q.pop_back(); + } + } else { visited.insert(e); vec.push_back(e); Q.pop_back(); - continue; - } - - std::set::iterator l = find_leader(VN, set, e.lhs); - std::set::iterator r = find_leader(VN, set, e.rhs); - - if (l != set.end() && visited.find(*l) == visited.end()) - Q.push_back(*l); - else if (r != set.end() && visited.find(*r) == visited.end()) - Q.push_back(*r); - else { - vec.push_back(e); - visited.insert(e); - Q.pop_back(); } } } -void GVNPRE::dump(GVNPRE::ValueTable& VN, std::set& s) { - std::vector sorted; +void GVNPRE::dump(GVNPRE::ValueTable& VN, std::set& s) { + std::vector sorted; topo_sort(VN, s, sorted); DOUT << "{ "; - for (std::vector::iterator I = sorted.begin(), E = sorted.end(); + for (std::vector::iterator I = sorted.begin(), E = sorted.end(); I != E; ++I) { - DOUT << VN[*I] << ": "; - DOUT << "( "; - DOUT << (char)(I->opcode+48); - DOUT << ", "; - if (I->value == 0) - DOUT << "0"; - else - DEBUG(I->value->dump()); - DOUT << ", value." << I->lhs << ", value." << I->rhs << " ) "; + DEBUG((*I)->dump()); } DOUT << "}\n\n"; } -void GVNPRE::CalculateAvailOut(GVNPRE::ValueTable& VN, std::set& MS, +void GVNPRE::CalculateAvailOut(GVNPRE::ValueTable& VN, std::set& MS, DominatorTree::Node* DI, - std::set& currExps, + std::set& currExps, std::set& currPhis, - std::set& currTemps, - std::set& currAvail, - std::map > availOut) { + std::set& currTemps, + std::set& currAvail, + std::map > availOut) { BasicBlock* BB = DI->getBlock(); @@ -416,36 +292,37 @@ void GVNPRE::CalculateAvailOut(GVNPRE::ValueTable& VN, std::set& MS, // Handle binary ops... } else if (BinaryOperator* BO = dyn_cast(BI)) { - Expression leftValue = buildExpression(VN, BO->getOperand(0)); - Expression rightValue = buildExpression(VN, BO->getOperand(1)); + Value* leftValue = BO->getOperand(0); + Value* rightValue = BO->getOperand(1); - Expression e = add(VN, MS, BO); + add(VN, MS, BO); currExps.insert(leftValue); currExps.insert(rightValue); - currExps.insert(e); + currExps.insert(BO); - currTemps.insert(e); + currTemps.insert(BO); // Handle unsupported ops - } else { - Expression e = add(VN, MS, BI); - currTemps.insert(e); + } else if (!BI->isTerminator()){ + add(VN, MS, BI); + currTemps.insert(BI); } - - currAvail.insert(buildExpression(VN, BI)); + + if (!BI->isTerminator()) + currAvail.insert(BI); } } bool GVNPRE::runOnFunction(Function &F) { ValueTable VN; - std::set maximalSet; + std::set maximalSet; - std::map > generatedExpressions; + std::map > generatedExpressions; std::map > generatedPhis; - std::map > generatedTemporaries; - std::map > availableOut; - std::map > anticipatedIn; + std::map > generatedTemporaries; + std::map > availableOut; + std::map > anticipatedIn; DominatorTree &DT = getAnalysis(); @@ -456,10 +333,10 @@ bool GVNPRE::runOnFunction(Function &F) { E = df_end(DT.getRootNode()); DI != E; ++DI) { // Get the sets to update for this block - std::set& currExps = generatedExpressions[DI->getBlock()]; + std::set& currExps = generatedExpressions[DI->getBlock()]; std::set& currPhis = generatedPhis[DI->getBlock()]; - std::set& currTemps = generatedTemporaries[DI->getBlock()]; - std::set& currAvail = availableOut[DI->getBlock()]; + std::set& currTemps = generatedTemporaries[DI->getBlock()]; + std::set& currAvail = availableOut[DI->getBlock()]; CalculateAvailOut(VN, maximalSet, *DI, currExps, currPhis, currTemps, currAvail, availableOut); @@ -475,7 +352,7 @@ bool GVNPRE::runOnFunction(Function &F) { unsigned iterations = 0; while (changed) { changed = false; - std::set anticOut; + std::set anticOut; // Top-down walk of the postdominator tree for (df_iterator PDI = @@ -485,8 +362,8 @@ bool GVNPRE::runOnFunction(Function &F) { visited.insert(BB); - std::set& anticIn = anticipatedIn[BB]; - std::set old (anticIn.begin(), anticIn.end()); + std::set& anticIn = anticipatedIn[BB]; + std::set old (anticIn.begin(), anticIn.end()); if (BB->getTerminator()->getNumSuccessors() == 1) { if (visited.find(BB) == visited.end()) @@ -496,43 +373,43 @@ bool GVNPRE::runOnFunction(Function &F) { } else if (BB->getTerminator()->getNumSuccessors() > 1) { for (unsigned i = 0; i < BB->getTerminator()->getNumSuccessors(); ++i) { BasicBlock* currSucc = BB->getTerminator()->getSuccessor(i); - std::set temp; + std::set temp; if (visited.find(currSucc) == visited.end()) temp.insert(maximalSet.begin(), maximalSet.end()); else temp.insert(anticIn.begin(), anticIn.end()); anticIn.clear(); - std::insert_iterator > ai_ins(anticIn, + std::insert_iterator > ai_ins(anticIn, anticIn.begin()); std::set_difference(anticipatedIn[currSucc].begin(), anticipatedIn[currSucc].end(), temp.begin(), temp.end(), - ai_ins); + ai_ins, + ExprLT()); } } - std::set S; - std::insert_iterator > s_ins(S, S.begin()); + std::set S; + std::insert_iterator > s_ins(S, S.begin()); std::set_union(anticOut.begin(), anticOut.end(), generatedExpressions[BB].begin(), generatedExpressions[BB].end(), - s_ins); + s_ins, ExprLT()); anticIn.clear(); - std::insert_iterator > antic_ins(anticIn, + std::insert_iterator > antic_ins(anticIn, anticIn.begin()); std::set_difference(S.begin(), S.end(), generatedTemporaries[BB].begin(), generatedTemporaries[BB].end(), - antic_ins); + antic_ins, + ExprLT()); clean(VN, anticIn); - - if (old != anticIn) changed = true; @@ -557,6 +434,10 @@ bool GVNPRE::runOnFunction(Function &F) { DOUT << "ANTIC_IN: "; dump(VN, anticipatedIn[I]); DOUT << "\n"; + + DOUT << "AVAIL_OUT: "; + dump(VN, availableOut[I]); + DOUT << "\n"; } return false;