[llvm] r303200 - NewGVN: Fix PR 33051 by making sure we remove old store expressions
Davide Italiano via llvm-commits
llvm-commits at lists.llvm.org
Tue May 16 13:37:14 PDT 2017
I think we should be able to re-enable the flaky test after this one,
I'll do that in a minute.
On Tue, May 16, 2017 at 12:58 PM, Daniel Berlin via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: dannyb
> Date: Tue May 16 14:58:47 2017
> New Revision: 303200
>
> URL: http://llvm.org/viewvc/llvm-project?rev=303200&view=rev
> Log:
> NewGVN: Fix PR 33051 by making sure we remove old store expressions
> from the ExpressionToClass mapping.
>
> Modified:
> llvm/trunk/lib/Transforms/Scalar/NewGVN.cpp
>
> Modified: llvm/trunk/lib/Transforms/Scalar/NewGVN.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/NewGVN.cpp?rev=303200&r1=303199&r2=303200&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/NewGVN.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/NewGVN.cpp Tue May 16 14:58:47 2017
> @@ -642,6 +642,7 @@ private:
> void updateProcessedCount(Value *V);
> void verifyMemoryCongruency() const;
> void verifyIterationSettled(Function &F);
> + void verifyStoreExpressions() const;
> bool singleReachablePHIPath(const MemoryAccess *, const MemoryAccess *) const;
> BasicBlock *getBlockForValue(Value *V) const;
> void deleteExpression(const Expression *E) const;
> @@ -2003,7 +2004,6 @@ void NewGVN::moveValueToNewCongruenceCla
>
> // If it's not a memory use, set the MemoryAccess equivalence
> auto *InstMA = dyn_cast_or_null<MemoryDef>(MSSA->getMemoryAccess(I));
> - bool InstWasMemoryLeader = InstMA && OldClass->getMemoryLeader() == InstMA;
> if (InstMA)
> moveMemoryToNewCongruenceClass(I, InstMA, OldClass, NewClass);
> ValueToClass[I] = NewClass;
> @@ -2029,31 +2029,6 @@ void NewGVN::moveValueToNewCongruenceCla
> if (OldClass->getStoredValue())
> OldClass->setStoredValue(nullptr);
> }
> - // If we destroy the old access leader and it's a store, we have to
> - // effectively destroy the congruence class. When it comes to scalars,
> - // anything with the same value is as good as any other. That means that
> - // one leader is as good as another, and as long as you have some leader for
> - // the value, you are good.. When it comes to *memory states*, only one
> - // particular thing really represents the definition of a given memory
> - // state. Once it goes away, we need to re-evaluate which pieces of memory
> - // are really still equivalent. The best way to do this is to re-value
> - // number things. The only way to really make that happen is to destroy the
> - // rest of the class. In order to effectively destroy the class, we reset
> - // ExpressionToClass for each by using the ValueToExpression mapping. The
> - // members later get marked as touched due to the leader change. We will
> - // create new congruence classes, and the pieces that are still equivalent
> - // will end back together in a new class. If this becomes too expensive, it
> - // is possible to use a versioning scheme for the congruence classes to
> - // avoid the expressions finding this old class. Note that the situation is
> - // different for memory phis, becuase they are evaluated anew each time, and
> - // they become equal not by hashing, but by seeing if all operands are the
> - // same (or only one is reachable).
> - if (OldClass->getStoreCount() > 0 && InstWasMemoryLeader) {
> - DEBUG(dbgs() << "Kicking everything out of class " << OldClass->getID()
> - << " because MemoryAccess leader changed");
> - for (auto Member : *OldClass)
> - ExpressionToClass.erase(ValueToExpression.lookup(Member));
> - }
> OldClass->setLeader(getNextValueLeader(OldClass));
> OldClass->resetNextLeader();
> markValueLeaderChangeTouched(OldClass);
> @@ -2062,7 +2037,6 @@ void NewGVN::moveValueToNewCongruenceCla
>
> // Perform congruence finding on a given value numbering expression.
> void NewGVN::performCongruenceFinding(Instruction *I, const Expression *E) {
> - ValueToExpression[I] = E;
> // This is guaranteed to return something, since it will at least find
> // TOP.
>
> @@ -2132,6 +2106,18 @@ void NewGVN::performCongruenceFinding(In
> if (auto *CI = dyn_cast<CmpInst>(I))
> markPredicateUsersTouched(CI);
> }
> + // If we changed the class of the store, we want to ensure nothing finds the
> + // old store expression. In particular, loads do not compare against stored
> + // value, so they will find old store expressions (and associated class
> + // mappings) if we leave them in the table.
> + if (ClassChanged && isa<StoreExpression>(E)) {
> + auto *OldE = ValueToExpression.lookup(I);
> + // It could just be that the old class died. We don't want to erase it if we
> + // just moved classes.
> + if (OldE && isa<StoreExpression>(OldE) && !OldE->equals(*E))
> + ExpressionToClass.erase(OldE);
> + }
> + ValueToExpression[I] = E;
> }
>
> // Process the fact that Edge (from, to) is reachable, including marking
> @@ -2651,6 +2637,28 @@ void NewGVN::verifyIterationSettled(Func
> #endif
> }
>
> +// Verify that for each store expression in the expression to class mapping,
> +// only the latest appears, and multiple ones do not appear.
> +// Because loads do not use the stored value when doing equality with stores,
> +// if we don't erase the old store expressions from the table, a load can find
> +// a no-longer valid StoreExpression.
> +void NewGVN::verifyStoreExpressions() const {
> + DenseSet<std::pair<const Value *, const Value *>> StoreExpressionSet;
> + for (const auto &KV : ExpressionToClass) {
> + if (auto *SE = dyn_cast<StoreExpression>(KV.first)) {
> + // Make sure a version that will conflict with loads is not already there
> + auto Res =
> + StoreExpressionSet.insert({SE->getOperand(0), SE->getMemoryLeader()});
> + assert(Res.second &&
> + "Stored expression conflict exists in expression table");
> + auto *ValueExpr = ValueToExpression.lookup(SE->getStoreInst());
> + assert(ValueExpr && ValueExpr->equals(*SE) &&
> + "StoreExpression in ExpressionToClass is not latest "
> + "StoreExpression for value");
> + }
> + }
> +}
> +
> // This is the main value numbering loop, it iterates over the initial touched
> // instruction set, propagating value numbers, marking things touched, etc,
> // until the set of touched instructions is completely empty.
> @@ -2776,6 +2784,7 @@ bool NewGVN::runGVN() {
> iterateTouchedInstructions();
> verifyMemoryCongruency();
> verifyIterationSettled(F);
> + verifyStoreExpressions();
>
> Changed |= eliminateInstructions(F);
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
--
Davide
"There are no solved problems; there are only problems that are more
or less solved" -- Henri Poincare
More information about the llvm-commits
mailing list