From 62cf8babdb91f9cee7c8ea8829773df73969660b Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Wed, 27 Jun 2007 04:10:46 +0000 Subject: [PATCH] Add support for performing GVNPRE on the three vector-specific operations. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@37745 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/GVNPRE.cpp | 456 +++++++++++++++++++++++++++++-- 1 file changed, 436 insertions(+), 20 deletions(-) diff --git a/lib/Transforms/Scalar/GVNPRE.cpp b/lib/Transforms/Scalar/GVNPRE.cpp index cd501927638..2a218df3e3f 100644 --- a/lib/Transforms/Scalar/GVNPRE.cpp +++ b/lib/Transforms/Scalar/GVNPRE.cpp @@ -58,24 +58,30 @@ namespace { ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ, FCMPOGT, FCMPOGE, FCMPOLT, FCMPOLE, FCMPONE, FCMPORD, FCMPUNO, FCMPUEQ, FCMPUGT, FCMPUGE, - FCMPULT, FCMPULE, FCMPUNE }; + FCMPULT, FCMPULE, FCMPUNE, EXTRACT, INSERT, + SHUFFLE }; ExpressionOpcode opcode; - uint32_t leftVN; - uint32_t rightVN; + uint32_t firstVN; + uint32_t secondVN; + uint32_t thirdVN; bool operator< (const Expression& other) const { if (opcode < other.opcode) return true; else if (opcode > other.opcode) return false; - else if (leftVN < other.leftVN) + else if (firstVN < other.firstVN) return true; - else if (leftVN > other.leftVN) + else if (firstVN > other.firstVN) return false; - else if (rightVN < other.rightVN) + else if (secondVN < other.secondVN) return true; - else if (rightVN > other.rightVN) + else if (secondVN > other.secondVN) + return false; + else if (thirdVN < other.thirdVN) + return true; + else if (thirdVN > other.thirdVN) return false; else return false; @@ -92,6 +98,9 @@ namespace { Expression::ExpressionOpcode getOpcode(CmpInst* C); Expression create_expression(BinaryOperator* BO); Expression create_expression(CmpInst* C); + Expression create_expression(ShuffleVectorInst* V); + Expression create_expression(ExtractElementInst* C); + Expression create_expression(InsertElementInst* V); public: ValueTable() { nextValueNumber = 1; } uint32_t lookup_or_add(Value* V); @@ -218,8 +227,9 @@ ValueTable::Expression::ExpressionOpcode ValueTable::getOpcode(CmpInst* C) { ValueTable::Expression ValueTable::create_expression(BinaryOperator* BO) { Expression e; - e.leftVN = lookup_or_add(BO->getOperand(0)); - e.rightVN = lookup_or_add(BO->getOperand(1)); + e.firstVN = lookup_or_add(BO->getOperand(0)); + e.secondVN = lookup_or_add(BO->getOperand(1)); + e.thirdVN = 0; e.opcode = getOpcode(BO); return e; @@ -228,13 +238,47 @@ ValueTable::Expression ValueTable::create_expression(BinaryOperator* BO) { ValueTable::Expression ValueTable::create_expression(CmpInst* C) { Expression e; - e.leftVN = lookup_or_add(C->getOperand(0)); - e.rightVN = lookup_or_add(C->getOperand(1)); + e.firstVN = lookup_or_add(C->getOperand(0)); + e.secondVN = lookup_or_add(C->getOperand(1)); + e.thirdVN = 0; e.opcode = getOpcode(C); return e; } +ValueTable::Expression ValueTable::create_expression(ShuffleVectorInst* S) { + Expression e; + + e.firstVN = lookup_or_add(S->getOperand(0)); + e.secondVN = lookup_or_add(S->getOperand(1)); + e.thirdVN = lookup_or_add(S->getOperand(2)); + e.opcode = Expression::SHUFFLE; + + return e; +} + +ValueTable::Expression ValueTable::create_expression(ExtractElementInst* E) { + Expression e; + + e.firstVN = lookup_or_add(E->getOperand(0)); + e.secondVN = lookup_or_add(E->getOperand(1)); + e.thirdVN = 0; + e.opcode = Expression::EXTRACT; + + return e; +} + +ValueTable::Expression ValueTable::create_expression(InsertElementInst* I) { + Expression e; + + e.firstVN = lookup_or_add(I->getOperand(0)); + e.secondVN = lookup_or_add(I->getOperand(1)); + e.thirdVN = lookup_or_add(I->getOperand(2)); + e.opcode = Expression::INSERT; + + return e; +} + //===----------------------------------------------------------------------===// // ValueTable External Functions //===----------------------------------------------------------------------===// @@ -263,6 +307,45 @@ uint32_t ValueTable::lookup_or_add(Value* V) { } else if (CmpInst* C = dyn_cast(V)) { Expression e = create_expression(C); + std::map::iterator EI = expressionNumbering.find(e); + if (EI != expressionNumbering.end()) { + valueNumbering.insert(std::make_pair(V, EI->second)); + return EI->second; + } else { + expressionNumbering.insert(std::make_pair(e, nextValueNumber)); + valueNumbering.insert(std::make_pair(V, nextValueNumber)); + + return nextValueNumber++; + } + } else if (ShuffleVectorInst* U = dyn_cast(V)) { + Expression e = create_expression(U); + + std::map::iterator EI = expressionNumbering.find(e); + if (EI != expressionNumbering.end()) { + valueNumbering.insert(std::make_pair(V, EI->second)); + return EI->second; + } else { + expressionNumbering.insert(std::make_pair(e, nextValueNumber)); + valueNumbering.insert(std::make_pair(V, nextValueNumber)); + + return nextValueNumber++; + } + } else if (ExtractElementInst* U = dyn_cast(V)) { + Expression e = create_expression(U); + + std::map::iterator EI = expressionNumbering.find(e); + if (EI != expressionNumbering.end()) { + valueNumbering.insert(std::make_pair(V, EI->second)); + return EI->second; + } else { + expressionNumbering.insert(std::make_pair(e, nextValueNumber)); + valueNumbering.insert(std::make_pair(V, nextValueNumber)); + + return nextValueNumber++; + } + } else if (InsertElementInst* U = dyn_cast(V)) { + Expression e = create_expression(U); + std::map::iterator EI = expressionNumbering.find(e); if (EI != expressionNumbering.end()) { valueNumbering.insert(std::make_pair(V, EI->second)); @@ -445,7 +528,9 @@ Value* GVNPRE::phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) { if (V == 0) return 0; - if (isa(V) || isa(V)) { + // Binary Operations + if (isa(V) || isa(V) || + isa(V)) { User* U = cast(V); Value* newOp1 = 0; @@ -477,6 +562,8 @@ Value* GVNPRE::phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) { C->getPredicate(), newOp1, newOp2, C->getName()+".expr"); + else if (ExtractElementInst* E = dyn_cast(U)) + newVal = new ExtractElementInst(newOp1, newOp2, E->getName()+".expr"); uint32_t v = VN.lookup_or_add(newVal); @@ -490,6 +577,63 @@ Value* GVNPRE::phi_translate(Value* V, BasicBlock* pred, BasicBlock* succ) { return leader; } } + + // Ternary Operations + } else if (isa(V) || isa(V)) { + User* U = cast(V); + + Value* newOp1 = 0; + if (isa(U->getOperand(0))) + newOp1 = phi_translate(U->getOperand(0), pred, succ); + else + newOp1 = U->getOperand(0); + + if (newOp1 == 0) + return 0; + + Value* newOp2 = 0; + if (isa(U->getOperand(1))) + newOp2 = phi_translate(U->getOperand(1), pred, succ); + else + newOp2 = U->getOperand(1); + + if (newOp2 == 0) + return 0; + + Value* newOp3 = 0; + if (isa(U->getOperand(2))) + newOp3 = phi_translate(U->getOperand(2), pred, succ); + else + newOp3 = U->getOperand(2); + + if (newOp3 == 0) + return 0; + + if (newOp1 != U->getOperand(0) || + newOp2 != U->getOperand(1) || + newOp3 != U->getOperand(2)) { + Instruction* newVal = 0; + if (ShuffleVectorInst* S = dyn_cast(U)) + newVal = new ShuffleVectorInst(newOp1, newOp2, newOp3, + S->getName()+".expr"); + else if (InsertElementInst* I = dyn_cast(U)) + newVal = new InsertElementInst(newOp1, newOp2, newOp3, + I->getName()+".expr"); + + uint32_t v = VN.lookup_or_add(newVal); + + Value* leader = find_leader(availableOut[pred], v); + if (leader == 0) { + createdExpressions.push_back(newVal); + return newVal; + } else { + VN.erase(newVal); + delete newVal; + return leader; + } + } + + // PHI Nodes } else if (PHINode* P = dyn_cast(V)) { if (P->getParent() == succ) return P->getIncomingValueForBlock(pred); @@ -583,6 +727,103 @@ void GVNPRE::clean(SmallPtrSet& set) { if (rhsValid) rhsValid = !dependsOnInvoke(C->getOperand(1)); + if (!lhsValid || !rhsValid) + set.erase(C); + } else if (ShuffleVectorInst* S = dyn_cast(v)) { + bool lhsValid = !isa(S->getOperand(0)); + if (!lhsValid) + for (SmallPtrSet::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN.lookup(*I) == VN.lookup(S->getOperand(0))) { + lhsValid = true; + break; + } + if (lhsValid) + lhsValid = !dependsOnInvoke(S->getOperand(0)); + + bool rhsValid = !isa(S->getOperand(1)); + if (!rhsValid) + for (SmallPtrSet::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN.lookup(*I) == VN.lookup(S->getOperand(1))) { + rhsValid = true; + break; + } + if (rhsValid) + rhsValid = !dependsOnInvoke(S->getOperand(1)); + + bool thirdValid = !isa(S->getOperand(2)); + if (!thirdValid) + for (SmallPtrSet::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN.lookup(*I) == VN.lookup(S->getOperand(2))) { + thirdValid = true; + break; + } + if (thirdValid) + thirdValid = !dependsOnInvoke(S->getOperand(2)); + + if (!lhsValid || !rhsValid || !thirdValid) + set.erase(C); + } else if (InsertElementInst* S = dyn_cast(v)) { + bool lhsValid = !isa(S->getOperand(0)); + if (!lhsValid) + for (SmallPtrSet::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN.lookup(*I) == VN.lookup(S->getOperand(0))) { + lhsValid = true; + break; + } + if (lhsValid) + lhsValid = !dependsOnInvoke(S->getOperand(0)); + + bool rhsValid = !isa(S->getOperand(1)); + if (!rhsValid) + for (SmallPtrSet::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN.lookup(*I) == VN.lookup(S->getOperand(1))) { + rhsValid = true; + break; + } + if (rhsValid) + rhsValid = !dependsOnInvoke(S->getOperand(1)); + + bool thirdValid = !isa(S->getOperand(2)); + if (!thirdValid) + for (SmallPtrSet::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN.lookup(*I) == VN.lookup(S->getOperand(2))) { + thirdValid = true; + break; + } + if (thirdValid) + thirdValid = !dependsOnInvoke(S->getOperand(2)); + + if (!lhsValid || !rhsValid || !thirdValid) + set.erase(C); + } else if (ExtractElementInst* C = dyn_cast(v)) { + bool lhsValid = !isa(C->getOperand(0)); + if (!lhsValid) + for (SmallPtrSet::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN.lookup(*I) == VN.lookup(C->getOperand(0))) { + lhsValid = true; + break; + } + if (lhsValid) + lhsValid = !dependsOnInvoke(C->getOperand(0)); + + bool rhsValid = !isa(C->getOperand(1)); + if (!rhsValid) + for (SmallPtrSet::iterator I = set.begin(), E = set.end(); + I != E; ++I) + if (VN.lookup(*I) == VN.lookup(C->getOperand(1))) { + rhsValid = true; + break; + } + if (rhsValid) + rhsValid = !dependsOnInvoke(C->getOperand(1)); + if (!lhsValid || !rhsValid) set.erase(C); } @@ -632,6 +873,59 @@ void GVNPRE::topo_sort(SmallPtrSet& set, std::vector& vec) { visited.insert(e); stack.pop_back(); } + } else if (ExtractElementInst* C = dyn_cast(e)) { + Value* l = find_leader(set, VN.lookup(C->getOperand(0))); + Value* r = find_leader(set, VN.lookup(C->getOperand(1))); + + if (l != 0 && isa(l) && + visited.count(l) == 0) + stack.push_back(l); + else if (r != 0 && isa(r) && + visited.count(r) == 0) + stack.push_back(r); + else { + vec.push_back(e); + visited.insert(e); + stack.pop_back(); + } + } else if (InsertElementInst* C = dyn_cast(e)) { + Value* l = find_leader(set, VN.lookup(C->getOperand(0))); + Value* r = find_leader(set, VN.lookup(C->getOperand(1))); + Value* m = find_leader(set, VN.lookup(C->getOperand(2))); + + if (l != 0 && isa(l) && + visited.count(l) == 0) + stack.push_back(l); + else if (r != 0 && isa(r) && + visited.count(r) == 0) + stack.push_back(r); + else if (m != 0 && isa(m) && + visited.count(m) == 0) + stack.push_back(r); + else { + vec.push_back(e); + visited.insert(e); + stack.pop_back(); + } + } else if (ShuffleVectorInst* C = dyn_cast(e)) { + Value* l = find_leader(set, VN.lookup(C->getOperand(0))); + Value* r = find_leader(set, VN.lookup(C->getOperand(1))); + Value* m = find_leader(set, VN.lookup(C->getOperand(2))); + + if (l != 0 && isa(l) && + visited.count(l) == 0) + stack.push_back(l); + else if (r != 0 && isa(r) && + visited.count(r) == 0) + stack.push_back(r); + else if (m != 0 && isa(m) && + visited.count(m) == 0) + stack.push_back(r); + else { + vec.push_back(e); + visited.insert(e); + stack.pop_back(); + } } else { visited.insert(e); vec.push_back(e); @@ -677,7 +971,9 @@ bool GVNPRE::elimination() { for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI) { - if (isa(BI) || isa(BI)) { + if (isa(BI) || isa(BI) || + isa(BI) || isa(BI) || + isa(BI)) { Value *leader = find_leader(availableOut[BB], VN.lookup(BI)); if (leader != 0) @@ -786,8 +1082,101 @@ void GVNPRE::buildsets_availout(BasicBlock::iterator I, expNumbers.set(num); } + // Handle extractelemt ops + } else if (InsertElementInst* C = dyn_cast(I)) { + Value* leftValue = C->getOperand(0); + Value* rightValue = C->getOperand(1); + Value* thirdValue = C->getOperand(2); + + VN.lookup_or_add(C); + + unsigned num = VN.lookup_or_add(C); + expNumbers.resize(VN.size()); + availNumbers.resize(VN.size()); + + if (isa(leftValue)) + if (!expNumbers.test(VN.lookup(leftValue))) { + currExps.insert(leftValue); + expNumbers.set(VN.lookup(leftValue)); + } + if (isa(rightValue)) + if (!expNumbers.test(VN.lookup(rightValue))) { + currExps.insert(rightValue); + expNumbers.set(VN.lookup(rightValue)); + } + if (isa(thirdValue)) + if (!expNumbers.test(VN.lookup(thirdValue))) { + currExps.insert(thirdValue); + expNumbers.set(VN.lookup(thirdValue)); + } + + if (!expNumbers.test(VN.lookup(C))) { + currExps.insert(C); + expNumbers.set(num); + } + + // Handle shufflevector ops + } else if (ShuffleVectorInst* C = dyn_cast(I)) { + Value* leftValue = C->getOperand(0); + Value* rightValue = C->getOperand(1); + Value* thirdValue = C->getOperand(2); + + VN.lookup_or_add(C); + + unsigned num = VN.lookup_or_add(C); + expNumbers.resize(VN.size()); + availNumbers.resize(VN.size()); + + if (isa(leftValue)) + if (!expNumbers.test(VN.lookup(leftValue))) { + currExps.insert(leftValue); + expNumbers.set(VN.lookup(leftValue)); + } + if (isa(rightValue)) + if (!expNumbers.test(VN.lookup(rightValue))) { + currExps.insert(rightValue); + expNumbers.set(VN.lookup(rightValue)); + } + if (isa(thirdValue)) + if (!expNumbers.test(VN.lookup(thirdValue))) { + currExps.insert(thirdValue); + expNumbers.set(VN.lookup(thirdValue)); + } + + if (!expNumbers.test(VN.lookup(C))) { + currExps.insert(C); + expNumbers.set(num); + } + + // Handle insertelement ops + } else if (ExtractElementInst* C = dyn_cast(I)) { + Value* leftValue = C->getOperand(0); + Value* rightValue = C->getOperand(1); + + VN.lookup_or_add(C); + + unsigned num = VN.lookup_or_add(C); + expNumbers.resize(VN.size()); + availNumbers.resize(VN.size()); + + if (isa(leftValue)) + if (!expNumbers.test(VN.lookup(leftValue))) { + currExps.insert(leftValue); + expNumbers.set(VN.lookup(leftValue)); + } + if (isa(rightValue)) + if (!expNumbers.test(VN.lookup(rightValue))) { + currExps.insert(rightValue); + expNumbers.set(VN.lookup(rightValue)); + } + + if (!expNumbers.test(VN.lookup(C))) { + currExps.insert(C); + expNumbers.set(num); + } + // Handle unsupported ops - } else if (!I->isTerminator()){ + }else if (!I->isTerminator()){ VN.lookup_or_add(I); expNumbers.resize(VN.size()); availNumbers.resize(VN.size()); @@ -995,17 +1384,35 @@ void GVNPRE::insertion_pre(Value* e, BasicBlock* BB, Value* s1 = 0; if (isa(U->getOperand(0)) || - isa(U->getOperand(0))) + isa(U->getOperand(0)) || + isa(U->getOperand(0)) || + isa(U->getOperand(0)) || + isa(U->getOperand(0))) s1 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(0))); else s1 = U->getOperand(0); Value* s2 = 0; - if (isa(U->getOperand(1)) || - isa(U->getOperand(1))) + if (isa(U->getOperand(1)) || + isa(U->getOperand(1)) || + isa(U->getOperand(1)) || + isa(U->getOperand(1)) || + isa(U->getOperand(1))) s2 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(1))); else s2 = U->getOperand(1); + + Value* s3 = 0; + if (isa(U) || + isa(U)) + if (isa(U->getOperand(2)) || + isa(U->getOperand(2)) || + isa(U->getOperand(2)) || + isa(U->getOperand(2)) || + isa(U->getOperand(2))) + s3 = find_leader(availableOut[*PI], VN.lookup(U->getOperand(2))); + else + s3 = U->getOperand(2); Value* newVal = 0; if (BinaryOperator* BO = dyn_cast(U)) @@ -1016,6 +1423,15 @@ void GVNPRE::insertion_pre(Value* e, BasicBlock* BB, newVal = CmpInst::create(C->getOpcode(), C->getPredicate(), s1, s2, C->getName()+".gvnpre", (*PI)->getTerminator()); + else if (ShuffleVectorInst* S = dyn_cast(U)) + newVal = new ShuffleVectorInst(s1, s2, s3, S->getName()+".gvnpre", + (*PI)->getTerminator()); + else if (InsertElementInst* S = dyn_cast(U)) + newVal = new InsertElementInst(s1, s2, s3, S->getName()+".gvnpre", + (*PI)->getTerminator()); + else if (ExtractElementInst* S = dyn_cast(U)) + newVal = new ExtractElementInst(s1, s2, S->getName()+".gvnpre", + (*PI)->getTerminator()); VN.add(newVal, VN.lookup(U)); @@ -1059,7 +1475,9 @@ unsigned GVNPRE::insertion_mergepoint(std::vector& workList, for (unsigned i = 0; i < workList.size(); ++i) { Value* e = workList[i]; - if (isa(e) || isa(e)) { + if (isa(e) || isa(e) || + isa(e) || isa(e) || + isa(e)) { if (find_leader(availableOut[D->getIDom()->getBlock()], VN.lookup(e)) != 0) continue; @@ -1179,8 +1597,6 @@ bool GVNPRE::runOnFunction(Function &F) { // Phase 1: BuildSets // This phase calculates the AVAIL_OUT and ANTIC_IN sets - // NOTE: If full postdom information is no available, this will bail - // early, performing GVN but not PRE buildsets(F); // Phase 2: Insert