diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-17 20:22:39 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-17 20:22:39 +0000 |
commit | 7af96fb3afd6725a2824a0a5ca5dad34e5e0b056 (patch) | |
tree | 6661ffbabf869009597684462f5a3df3beccc952 /lib/Transforms/Scalar | |
parent | 6b3f41ed88e8e440e11a4fbf20b6600529f80049 (diff) |
Vendor import of llvm trunk r303291:vendor/llvm/llvm-trunk-r303291
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=318414
svn path=/vendor/llvm/llvm-trunk-r303291/; revision=318415; tag=vendor/llvm/llvm-trunk-r303291
Diffstat (limited to 'lib/Transforms/Scalar')
-rw-r--r-- | lib/Transforms/Scalar/LICM.cpp | 2 | ||||
-rw-r--r-- | lib/Transforms/Scalar/LoopIdiomRecognize.cpp | 16 | ||||
-rw-r--r-- | lib/Transforms/Scalar/LoopStrengthReduce.cpp | 3 | ||||
-rw-r--r-- | lib/Transforms/Scalar/NewGVN.cpp | 68 | ||||
-rw-r--r-- | lib/Transforms/Scalar/Reassociate.cpp | 2 | ||||
-rw-r--r-- | lib/Transforms/Scalar/SimpleLoopUnswitch.cpp | 37 |
6 files changed, 79 insertions, 49 deletions
diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp index 340c81fed0fd..37b9c4b1094e 100644 --- a/lib/Transforms/Scalar/LICM.cpp +++ b/lib/Transforms/Scalar/LICM.cpp @@ -546,7 +546,7 @@ static bool isLoadInvariantInLoop(LoadInst *LI, DominatorTree *DT, // If there are escaping uses of invariant.start instruction, the load maybe // non-invariant. if (!II || II->getIntrinsicID() != Intrinsic::invariant_start || - II->hasNUsesOrMore(1)) + !II->use_empty()) continue; unsigned InvariantSizeInBits = cast<ConstantInt>(II->getArgOperand(0))->getSExtValue() * 8; diff --git a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp index 6693a26e8890..cb6223b070a6 100644 --- a/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ b/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -1292,13 +1292,15 @@ bool LoopIdiomRecognize::recognizeAndInsertCTLZ() { BasicBlock *PH = CurLoop->getLoopPreheader(); Value *InitX = PhiX->getIncomingValueForBlock(PH); // If we check X != 0 before entering the loop we don't need a zero - // check in CTLZ intrinsic. - if (BasicBlock *PreCondBB = PH->getSinglePredecessor()) - if (BranchInst *PreCondBr = - dyn_cast<BranchInst>(PreCondBB->getTerminator())) { - if (matchCondition(PreCondBr, PH) == InitX) - ZeroCheck = true; - } + // check in CTLZ intrinsic, but only if Cnt Phi is not used outside of the + // loop (if it is used we count CTLZ(X >> 1)). + if (!IsCntPhiUsedOutsideLoop) + if (BasicBlock *PreCondBB = PH->getSinglePredecessor()) + if (BranchInst *PreCondBr = + dyn_cast<BranchInst>(PreCondBB->getTerminator())) { + if (matchCondition(PreCondBr, PH) == InitX) + ZeroCheck = true; + } // Check if CTLZ intrinsic is profitable. Assume it is always profitable // if we delete the loop (the loop has only 6 instructions): diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp index ccedb98d7fa1..bd1f21c69eba 100644 --- a/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -3902,8 +3902,7 @@ void LSRInstance::GenerateCrossUseConstantOffsets() { // Compute the difference between the two. int64_t Imm = (uint64_t)JImm - M->first; - for (int LUIdx = UsedByIndices.find_first(); LUIdx != -1; - LUIdx = UsedByIndices.find_next(LUIdx)) + for (unsigned LUIdx : UsedByIndices.set_bits()) // Make a memo of this use, offset, and register tuple. if (UniqueItems.insert(std::make_pair(LUIdx, Imm)).second) WorkItems.push_back(WorkItem(LUIdx, Imm, OrigReg)); diff --git a/lib/Transforms/Scalar/NewGVN.cpp b/lib/Transforms/Scalar/NewGVN.cpp index 5e0a705782ea..0e7572f8d2e5 100644 --- a/lib/Transforms/Scalar/NewGVN.cpp +++ b/lib/Transforms/Scalar/NewGVN.cpp @@ -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::moveValueToNewCongruenceClass(Instruction *I, const Expression *E, // 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::moveValueToNewCongruenceClass(Instruction *I, const Expression *E, 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::moveValueToNewCongruenceClass(Instruction *I, const Expression *E, // 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(Instruction *I, const Expression *E) { 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,30 @@ void NewGVN::verifyIterationSettled(Function &F) { #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 { +#ifndef NDEBUG + 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"); + } + } +#endif +} + // 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. @@ -2668,8 +2678,7 @@ void NewGVN::iterateTouchedInstructions() { // 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)) { + for (unsigned InstrNum : TouchedInstructions.set_bits()) { // This instruction was found to be dead. We don't bother looking // at it again. @@ -2776,6 +2785,7 @@ bool NewGVN::runGVN() { iterateTouchedInstructions(); verifyMemoryCongruency(); verifyIterationSettled(F); + verifyStoreExpressions(); Changed |= eliminateInstructions(F); diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp index ef29d4141600..53320bff0883 100644 --- a/lib/Transforms/Scalar/Reassociate.cpp +++ b/lib/Transforms/Scalar/Reassociate.cpp @@ -1922,7 +1922,7 @@ Instruction *ReassociatePass::canonicalizeNegConstExpr(Instruction *I) { // User must be a binary operator with one or more uses. Instruction *User = I->user_back(); - if (!isa<BinaryOperator>(User) || !User->hasNUsesOrMore(1)) + if (!isa<BinaryOperator>(User) || User->use_empty()) return nullptr; unsigned UserOpcode = User->getOpcode(); diff --git a/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp b/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp index 4f608c97147d..b32a61a7e8f8 100644 --- a/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp +++ b/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp @@ -1,4 +1,4 @@ -//===-- SimpleLoopUnswitch.cpp - Hoist loop-invariant control flow --------===// +//===- SimpleLoopUnswitch.cpp - Hoist loop-invariant control flow ---------===// // // The LLVM Compiler Infrastructure // @@ -7,25 +7,41 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h" -#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Sequence.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Twine.h" #include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/LoopAnalysisManager.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" -#include "llvm/Support/CommandLine.h" +#include "llvm/IR/Use.h" +#include "llvm/IR/Value.h" +#include "llvm/Pass.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/GenericDomTree.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Transforms/Utils/Local.h" -#include "llvm/Transforms/Scalar/LoopPassManager.h" #include "llvm/Transforms/Utils/LoopUtils.h" +#include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h" +#include <algorithm> +#include <cassert> +#include <iterator> +#include <utility> #define DEBUG_TYPE "simple-loop-unswitch" @@ -174,7 +190,7 @@ static void rewritePHINodesForUnswitchedExitBlock(BasicBlock &UnswitchedBB, // When the loop exit is directly unswitched we just need to update the // incoming basic block. We loop to handle weird cases with repeated // incoming blocks, but expect to typically only have one operand here. - for (auto i : llvm::seq<int>(0, PN->getNumOperands())) { + for (auto i : seq<int>(0, PN->getNumOperands())) { assert(PN->getIncomingBlock(i) == &OldExitingBB && "Found incoming block different from unique predecessor!"); PN->setIncomingBlock(i, &OldPH); @@ -688,9 +704,11 @@ PreservedAnalyses SimpleLoopUnswitchPass::run(Loop &L, LoopAnalysisManager &AM, } namespace { + class SimpleLoopUnswitchLegacyPass : public LoopPass { public: static char ID; // Pass ID, replacement for typeid + explicit SimpleLoopUnswitchLegacyPass() : LoopPass(ID) { initializeSimpleLoopUnswitchLegacyPassPass( *PassRegistry::getPassRegistry()); @@ -703,7 +721,8 @@ public: getLoopAnalysisUsage(AU); } }; -} // namespace + +} // end anonymous namespace bool SimpleLoopUnswitchLegacyPass::runOnLoop(Loop *L, LPPassManager &LPM) { if (skipLoop(L)) |