diff options
| author | Daniel Berlin <dberlin@dberlin.org> | 2017-02-18 23:06:50 +0000 |
|---|---|---|
| committer | Daniel Berlin <dberlin@dberlin.org> | 2017-02-18 23:06:50 +0000 |
| commit | f7d9580a087ee0c55b64dcb3ac9ef9adce8b3d83 (patch) | |
| tree | d7b7358ec53e24254d381835f1cd97dd1ea69b28 /llvm/lib/Transforms | |
| parent | b355c4ff5f75eac95a67c4e0d9da449616ed5103 (diff) | |
| download | bcm5719-llvm-f7d9580a087ee0c55b64dcb3ac9ef9adce8b3d83.tar.gz bcm5719-llvm-f7d9580a087ee0c55b64dcb3ac9ef9adce8b3d83.zip | |
NewGVN: Start making use of predicateinfo pass.
Summary: This begins using the predicateinfo pass in NewGVN.
Reviewers: davide
Subscribers: llvm-commits, Prazek
Differential Revision: https://reviews.llvm.org/D29682
llvm-svn: 295583
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Scalar/NewGVN.cpp | 293 |
1 files changed, 275 insertions, 18 deletions
diff --git a/llvm/lib/Transforms/Scalar/NewGVN.cpp b/llvm/lib/Transforms/Scalar/NewGVN.cpp index 8989d5cc2cc..f08df2b6b43 100644 --- a/llvm/lib/Transforms/Scalar/NewGVN.cpp +++ b/llvm/lib/Transforms/Scalar/NewGVN.cpp @@ -81,13 +81,13 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/MemorySSA.h" +#include "llvm/Transforms/Utils/PredicateInfo.h" #include <unordered_map> #include <utility> #include <vector> using namespace llvm; using namespace PatternMatch; using namespace llvm::GVNExpression; - #define DEBUG_TYPE "newgvn" STATISTIC(NumGVNInstrDeleted, "Number of instructions deleted"); @@ -209,6 +209,7 @@ class NewGVN : public FunctionPass { AliasAnalysis *AA; MemorySSA *MSSA; MemorySSAWalker *MSSAWalker; + std::unique_ptr<PredicateInfo> PredInfo; BumpPtrAllocator ExpressionAllocator; ArrayRecycler<Value *> ArgRecycler; @@ -229,6 +230,12 @@ class NewGVN : public FunctionPass { DenseMap<Value *, CongruenceClass *> ValueToClass; DenseMap<Value *, const Expression *> ValueToExpression; + // Mapping from predicate info we used to the instructions we used it with. + // In order to correctly ensure propagation, we must keep track of what + // comparisons we used, so that when the values of the comparisons change, we + // propagate the information to the places we used the comparison. + DenseMap<const Value *, SmallPtrSet<Instruction *, 2>> PredicateToUsers; + // A table storing which memorydefs/phis represent a memory state provably // equivalent to another memory state. // We could use the congruence class machinery, but the MemoryAccess's are @@ -297,7 +304,6 @@ private: AU.addRequired<TargetLibraryInfoWrapperPass>(); AU.addRequired<MemorySSAWrapperPass>(); AU.addRequired<AAResultsWrapperPass>(); - AU.addPreserved<DominatorTreeWrapperPass>(); AU.addPreserved<GlobalsAAWrapperPass>(); } @@ -308,6 +314,7 @@ private: PHIExpression *createPHIExpression(Instruction *); const VariableExpression *createVariableExpression(Value *); const ConstantExpression *createConstantExpression(Constant *); + const Expression *createVariableOrConstant(Value *V); const UnknownExpression *createUnknownExpression(Instruction *); const StoreExpression *createStoreExpression(StoreInst *, MemoryAccess *); LoadExpression *createLoadExpression(Type *, Value *, LoadInst *, @@ -345,6 +352,7 @@ private: const Expression *performSymbolicPHIEvaluation(Instruction *); const Expression *performSymbolicAggrValueEvaluation(Instruction *); const Expression *performSymbolicCmpEvaluation(Instruction *); + const Expression *performSymbolicPredicateInfoEvaluation(Instruction *); // Congruence finding. Value *lookupOperandLeader(Value *) const; @@ -382,13 +390,16 @@ private: // Various instruction touch utilities void markUsersTouched(Value *); void markMemoryUsersTouched(MemoryAccess *); + void markPredicateUsersTouched(Instruction *); void markLeaderChangeTouched(CongruenceClass *CC); + void addPredicateUsers(const PredicateBase *, Instruction *); // Utilities. void cleanupTables(); std::pair<unsigned, unsigned> assignDFSNumbers(BasicBlock *, unsigned); void updateProcessedCount(Value *V); void verifyMemoryCongruency() const; + void verifyComparisons(Function &F); bool singleReachablePHIPath(const MemoryAccess *, const MemoryAccess *) const; }; } // end anonymous namespace @@ -669,6 +680,12 @@ const VariableExpression *NewGVN::createVariableExpression(Value *V) { return E; } +const Expression *NewGVN::createVariableOrConstant(Value *V) { + if (auto *C = dyn_cast<Constant>(V)) + return createConstantExpression(C); + return createVariableExpression(V); +} + const ConstantExpression *NewGVN::createConstantExpression(Constant *C) { auto *E = new (ExpressionAllocator) ConstantExpression(C); E->setOpcode(C->getValueID()); @@ -831,12 +848,103 @@ const Expression *NewGVN::performSymbolicLoadEvaluation(Instruction *I) { return E; } +const Expression * +NewGVN::performSymbolicPredicateInfoEvaluation(Instruction *I) { + auto *PI = PredInfo->getPredicateInfoFor(I); + if (!PI) + return nullptr; + + DEBUG(dbgs() << "Found predicate info from instruction !\n"); + auto *CopyOf = I->getOperand(0); + auto *Cond = dyn_cast<Instruction>(PI->Condition); + if (!Cond) + return nullptr; + + // If this a copy of the condition, it must be either true or false depending + // on the predicate info type and edge + if (CopyOf == Cond) { + addPredicateUsers(PI, I); + if (isa<PredicateAssume>(PI)) + return createConstantExpression(ConstantInt::getTrue(Cond->getType())); + if (auto *PBranch = dyn_cast<PredicateBranch>(PI)) { + if (PBranch->TrueEdge) + return createConstantExpression(ConstantInt::getTrue(Cond->getType())); + return createConstantExpression(ConstantInt::getFalse(Cond->getType())); + } + } + // Not a copy of the condition, so see what the predicates tell us about this + // value. + // Not a copy of the condition, so see what the predicates tell us about this + // value. First, though, we check to make sure the value is actually a copy + // of one of the condition operands. It's possible, in certain cases, for it + // to be a copy of a predicateinfo copy. In particular, if two branch + // operations use the same condition, and one branch dominates the other, we + // will end up with a copy of a copy. This is currently a small deficiency in + // predicateinfo. What will end up happening here is that we will value + // number both copies the same anyway. + if (CopyOf != Cond->getOperand(0) && CopyOf != Cond->getOperand(1)) { + DEBUG(dbgs() << "Copy is not of any condition operands!"); + return nullptr; + } + Value *FirstOp = lookupOperandLeader(Cond->getOperand(0)); + Value *SecondOp = lookupOperandLeader(Cond->getOperand(1)); + bool SwappedOps = false; + // Sort the ops + if (shouldSwapOperands(FirstOp, SecondOp)) { + std::swap(FirstOp, SecondOp); + SwappedOps = true; + } + + // Everything below relies on the condition being a comparison. + auto *Cmp = dyn_cast<CmpInst>(Cond); + CmpInst::Predicate Predicate = + SwappedOps ? Cmp->getSwappedPredicate() : Cmp->getPredicate(); + + if (isa<PredicateAssume>(PI)) { + // If the comparison is true when the operands are equal, then we know the + // operands are equal, because assumes must always be true. + if (CmpInst::isTrueWhenEqual(Predicate)) { + addPredicateUsers(PI, I); + return createVariableOrConstant(FirstOp); + } + } + if (const auto *PBranch = dyn_cast<PredicateBranch>(PI)) { + // If we are *not* a copy of the comparison, we may equal to the other + // operand when the predicate implies something about equality of + // operations. In particular, if the comparison is true/false when the + // operands are equal, and we are on the right edge, we know this operation + // is equal to something. + if ((PBranch->TrueEdge && Predicate == CmpInst::ICMP_EQ) || + (!PBranch->TrueEdge && Predicate == CmpInst::ICMP_NE)) { + addPredicateUsers(PI, I); + return createVariableOrConstant(FirstOp); + } + // Handle the special case of floating point. + if (((PBranch->TrueEdge && Predicate == CmpInst::FCMP_OEQ) || + (!PBranch->TrueEdge && Predicate == CmpInst::FCMP_UNE)) && + isa<ConstantFP>(FirstOp) && !cast<ConstantFP>(FirstOp)->isZero()) { + addPredicateUsers(PI, I); + return createConstantExpression(cast<Constant>(FirstOp)); + } + } + return nullptr; +} + // Evaluate read only and pure calls, and create an expression result. const Expression *NewGVN::performSymbolicCallEvaluation(Instruction *I) { auto *CI = cast<CallInst>(I); - if (AA->doesNotAccessMemory(CI)) + if (auto *II = dyn_cast<IntrinsicInst>(I)) { + // Instrinsics with the returned attribute are copies of arguments. + if (auto *ReturnedValue = II->getReturnedArgOperand()) { + if (II->getIntrinsicID() == Intrinsic::ssa_copy) + if (const auto *Result = performSymbolicPredicateInfoEvaluation(I)) + return Result; + return createVariableOrConstant(ReturnedValue); + } + } + if (AA->doesNotAccessMemory(CI)) { return createCallExpression(CI, nullptr); - if (AA->onlyReadsMemory(CI)) { + } else if (AA->onlyReadsMemory(CI)) { MemoryAccess *DefiningAccess = MSSAWalker->getClobberingMemoryAccess(CI); return createCallExpression(CI, lookupMemoryAccessEquiv(DefiningAccess)); } @@ -930,9 +1038,7 @@ const Expression *NewGVN::performSymbolicPHIEvaluation(Instruction *I) { << "\n"); E->deallocateOperands(ArgRecycler); ExpressionAllocator.Deallocate(E); - if (auto *C = dyn_cast<Constant>(AllSameValue)) - return createConstantExpression(C); - return createVariableExpression(AllSameValue); + return createVariableOrConstant(AllSameValue); } return E; } @@ -976,16 +1082,117 @@ const Expression *NewGVN::performSymbolicAggrValueEvaluation(Instruction *I) { return createAggregateValueExpression(I); } const Expression *NewGVN::performSymbolicCmpEvaluation(Instruction *I) { - CmpInst *CI = dyn_cast<CmpInst>(I); - // See if our operands are equal and that implies something. + auto *CI = dyn_cast<CmpInst>(I); + // See if our operands are equal to those of a previous predicate, and if so, + // if it implies true or false. auto Op0 = lookupOperandLeader(CI->getOperand(0)); auto Op1 = lookupOperandLeader(CI->getOperand(1)); + auto OurPredicate = CI->getPredicate(); + if (shouldSwapOperands(Op1, Op0)) { + std::swap(Op0, Op1); + OurPredicate = CI->getSwappedPredicate(); + } + + // Avoid processing the same info twice + const PredicateBase *LastPredInfo = nullptr; + + // See if we know something about the comparison itself, like it is the target + // of an assume. + auto *CmpPI = PredInfo->getPredicateInfoFor(I); + if (dyn_cast_or_null<PredicateAssume>(CmpPI)) + return createConstantExpression(ConstantInt::getTrue(CI->getType())); + if (Op0 == Op1) { + // This condition does not depend on predicates, no need to add users if (CI->isTrueWhenEqual()) return createConstantExpression(ConstantInt::getTrue(CI->getType())); else if (CI->isFalseWhenEqual()) return createConstantExpression(ConstantInt::getFalse(CI->getType())); } + + // NOTE: Because we are comparing both operands here and below, and using + // previous comparisons, we rely on fact that predicateinfo knows to mark + // comparisons that use renamed operands as users of the earlier comparisons. + // It is *not* enough to just mark predicateinfo renamed operands as users of + // the earlier comparisons, because the *other* operand may have changed in a + // previous iteration. + // Example: + // icmp slt %a, %b + // %b.0 = ssa.copy(%b) + // false branch: + // icmp slt %c, %b.0 + + // %c and %a may start out equal, and thus, the code below will say the second + // %icmp is false. c may become equal to something else, and in that case the + // %second icmp *must* be reexamined, but would not if only the renamed + // %operands are considered users of the icmp. + + // *Currently* we only check one level of comparisons back, and only mark one + // level back as touched when changes appen . If you modify this code to look + // back farther through comparisons, you *must* mark the appropriate + // comparisons as users in PredicateInfo.cpp, or you will cause bugs. See if + // we know something just from the operands themselves + + // See if our operands have predicate info, so that we may be able to derive + // something from a previous comparison. + for (const auto &Op : CI->operands()) { + auto *PI = PredInfo->getPredicateInfoFor(Op); + if (const auto *PBranch = dyn_cast_or_null<PredicateBranch>(PI)) { + if (PI == LastPredInfo) + continue; + LastPredInfo = PI; + // TODO: Along the false edge, we may know more things too, like icmp of + // same operands is false. + // TODO: We only handle actual comparison conditions below, not and/or. + auto *BranchCond = dyn_cast<CmpInst>(PBranch->Condition); + if (!BranchCond) + continue; + auto *BranchOp0 = lookupOperandLeader(BranchCond->getOperand(0)); + auto *BranchOp1 = lookupOperandLeader(BranchCond->getOperand(1)); + auto BranchPredicate = BranchCond->getPredicate(); + if (shouldSwapOperands(BranchOp1, BranchOp0)) { + std::swap(BranchOp0, BranchOp1); + BranchPredicate = BranchCond->getSwappedPredicate(); + } + if (BranchOp0 == Op0 && BranchOp1 == Op1) { + if (PBranch->TrueEdge) { + // If we know the previous predicate is true and we are in the true + // edge then we may be implied true or false. + if (CmpInst::isImpliedTrueByMatchingCmp(OurPredicate, + BranchPredicate)) { + addPredicateUsers(PI, I); + return createConstantExpression( + ConstantInt::getTrue(CI->getType())); + } + + if (CmpInst::isImpliedFalseByMatchingCmp(OurPredicate, + BranchPredicate)) { + addPredicateUsers(PI, I); + return createConstantExpression( + ConstantInt::getFalse(CI->getType())); + } + + } else { + // Just handle the ne and eq cases, where if we have the same + // operands, we may know something. + if (BranchPredicate == OurPredicate) { + addPredicateUsers(PI, I); + // Same predicate, same ops,we know it was false, so this is false. + return createConstantExpression( + ConstantInt::getFalse(CI->getType())); + } else if (BranchPredicate == + CmpInst::getInversePredicate(OurPredicate)) { + addPredicateUsers(PI, I); + // Inverse predicate, we know the other was false, so this is true. + // FIXME: Double check this + return createConstantExpression( + ConstantInt::getTrue(CI->getType())); + } + } + } + } + } + // Create expression will take care of simplifyCmpInst return createExpression(I); } @@ -1085,6 +1292,22 @@ void NewGVN::markMemoryUsersTouched(MemoryAccess *MA) { } } +// Add I to the set of users of a given predicate. +void NewGVN::addPredicateUsers(const PredicateBase *PB, Instruction *I) { + if (auto *PBranch = dyn_cast<PredicateBranch>(PB)) + PredicateToUsers[PBranch->Condition].insert(I); + else if (auto *PAssume = dyn_cast<PredicateBranch>(PB)) + PredicateToUsers[PAssume->Condition].insert(I); +} + +// Touch all the predicates that depend on this instruction. +void NewGVN::markPredicateUsersTouched(Instruction *I) { + const auto Result = PredicateToUsers.find(I); + if (Result != PredicateToUsers.end()) + for (auto *User : Result->second) + TouchedInstructions.set(InstrDFS.lookup(User)); +} + // Touch the instructions that need to be updated after a congruence class has a // leader change, and mark changed values. void NewGVN::markLeaderChangeTouched(CongruenceClass *CC) { @@ -1286,6 +1509,8 @@ void NewGVN::performCongruenceFinding(Instruction *I, const Expression *E) { markUsersTouched(I); if (MemoryAccess *MA = MSSA->getMemoryAccess(I)) markMemoryUsersTouched(MA); + if (auto *CI = dyn_cast<CmpInst>(I)) + markPredicateUsersTouched(CI); } } @@ -1481,6 +1706,7 @@ void NewGVN::cleanupTables() { TouchedInstructions.clear(); DominatedInstRange.clear(); MemoryAccessToClass.clear(); + PredicateToUsers.clear(); } std::pair<unsigned, unsigned> NewGVN::assignDFSNumbers(BasicBlock *B, @@ -1681,6 +1907,27 @@ void NewGVN::verifyMemoryCongruency() const { } } +// Re-evaluate all the comparisons after value numbering and ensure they don't +// change. If they changed, we didn't mark them touched properly. +void NewGVN::verifyComparisons(Function &F) { +#ifndef NDEBUG + for (auto &BB : F) { + if (!ReachableBlocks.count(&BB)) + continue; + for (auto &I : BB) { + if (InstructionsToErase.count(&I)) + continue; + if (isa<CmpInst>(&I)) { + auto *CurrentVal = ValueToClass.lookup(&I); + valueNumberInstruction(&I); + assert(CurrentVal == ValueToClass.lookup(&I) && + "Re-evaluating comparison changed value"); + } + } + } +#endif +} + // This is the main transformation entry point. bool NewGVN::runGVN(Function &F, DominatorTree *_DT, AssumptionCache *_AC, TargetLibraryInfo *_TLI, AliasAnalysis *_AA, @@ -1692,6 +1939,7 @@ bool NewGVN::runGVN(Function &F, DominatorTree *_DT, AssumptionCache *_AC, TLI = _TLI; AA = _AA; MSSA = _MSSA; + PredInfo = make_unique<PredicateInfo>(F, *DT, *AC); DL = &F.getParent()->getDataLayout(); MSSAWalker = MSSA->getWalker(); @@ -1700,9 +1948,9 @@ bool NewGVN::runGVN(Function &F, DominatorTree *_DT, AssumptionCache *_AC, unsigned ICount = 1; // Add an empty instruction to account for the fact that we start at 1 DFSToInstr.emplace_back(nullptr); - // Note: We want RPO traversal of the blocks, which is not quite the same as - // dominator tree order, particularly with regard whether backedges get - // visited first or second, given a block with multiple successors. + // Note: We want ideal RPO traversal of the blocks, which is not quite the + // same as dominator tree order, particularly with regard whether backedges + // get visited first or second, given a block with multiple successors. // If we visit in the wrong order, we will end up performing N times as many // iterations. // The dominator tree does guarantee that, for a given dom tree node, it's @@ -1766,6 +2014,9 @@ bool NewGVN::runGVN(Function &F, DominatorTree *_DT, AssumptionCache *_AC, while (TouchedInstructions.any()) { ++Iterations; // Walk through all the instructions in all the blocks in RPO. + // TODO: As we hit a new block, we should push and pop equalities into a + // table lookupOperandLeader can use, to catch things PredicateInfo + // might miss, like edge-only equivalences. for (int InstrNum = TouchedInstructions.find_first(); InstrNum != -1; InstrNum = TouchedInstructions.find_next(InstrNum)) { @@ -1820,7 +2071,9 @@ bool NewGVN::runGVN(Function &F, DominatorTree *_DT, AssumptionCache *_AC, NumGVNMaxIterations = std::max(NumGVNMaxIterations.getValue(), Iterations); #ifndef NDEBUG verifyMemoryCongruency(); + verifyComparisons(F); #endif + Changed |= eliminateInstructions(F); // Delete all instructions marked for deletion. @@ -2295,15 +2548,14 @@ bool NewGVN::eliminateInstructions(Function &F) { // start using, we also push. // Otherwise, we walk along, processing members who are // dominated by this scope, and eliminate them. - bool ShouldPush = - Member && (EliminationStack.empty() || isa<Constant>(Member)); + bool ShouldPush = Member && EliminationStack.empty(); bool OutOfScope = !EliminationStack.isInScope(MemberDFSIn, MemberDFSOut); if (OutOfScope || ShouldPush) { // Sync to our current scope. EliminationStack.popUntilDFSScope(MemberDFSIn, MemberDFSOut); - ShouldPush |= Member && EliminationStack.empty(); + bool ShouldPush = Member && EliminationStack.empty(); if (ShouldPush) { EliminationStack.push_back(Member, MemberDFSIn, MemberDFSOut); } @@ -2329,8 +2581,13 @@ bool NewGVN::eliminateInstructions(Function &F) { // If we replaced something in an instruction, handle the patching of // metadata. - if (auto *ReplacedInst = dyn_cast<Instruction>(MemberUse->get())) - patchReplacementInstruction(ReplacedInst, Result); + if (auto *ReplacedInst = dyn_cast<Instruction>(MemberUse->get())) { + // Skip this if we are replacing predicateinfo with its original + // operand, as we already know we can just drop it. + auto *PI = PredInfo->getPredicateInfoFor(ReplacedInst); + if (!PI || Result != PI->OriginalOp) + patchReplacementInstruction(ReplacedInst, Result); + } assert(isa<Instruction>(MemberUse->getUser())); MemberUse->set(Result); @@ -2425,5 +2682,5 @@ bool NewGVN::shouldSwapOperands(const Value *A, const Value *B) const { // Because we only care about a total ordering, and don't rewrite expressions // in this order, we order by rank, which will give a strict weak ordering to // everything but constants, and then we order by pointer address. - return std::make_pair(getRank(A), A) > std::make_pair(getRank(B), B); + return std::make_pair(getRank(A), A) > std::make_pair(getRank(B), B); } |

