diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 10:51:19 +0000 |
commit | eb11fae6d08f479c0799db45860a98af528fa6e7 (patch) | |
tree | 44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/Transforms/Scalar/LoopLoadElimination.cpp | |
parent | b8a2042aa938069e862750553db0e4d82d25822c (diff) |
Notes
Diffstat (limited to 'lib/Transforms/Scalar/LoopLoadElimination.cpp')
-rw-r--r-- | lib/Transforms/Scalar/LoopLoadElimination.cpp | 82 |
1 files changed, 44 insertions, 38 deletions
diff --git a/lib/Transforms/Scalar/LoopLoadElimination.cpp b/lib/Transforms/Scalar/LoopLoadElimination.cpp index dfa5ec1f354d..19bd9ebcc15b 100644 --- a/lib/Transforms/Scalar/LoopLoadElimination.cpp +++ b/lib/Transforms/Scalar/LoopLoadElimination.cpp @@ -25,7 +25,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -52,6 +52,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils.h" #include "llvm/Transforms/Utils/LoopVersioning.h" #include <algorithm> #include <cassert> @@ -79,7 +80,7 @@ STATISTIC(NumLoopLoadEliminted, "Number of loads eliminated by LLE"); namespace { -/// \brief Represent a store-to-forwarding candidate. +/// Represent a store-to-forwarding candidate. struct StoreToLoadForwardingCandidate { LoadInst *Load; StoreInst *Store; @@ -87,7 +88,7 @@ struct StoreToLoadForwardingCandidate { StoreToLoadForwardingCandidate(LoadInst *Load, StoreInst *Store) : Load(Load), Store(Store) {} - /// \brief Return true if the dependence from the store to the load has a + /// Return true if the dependence from the store to the load has a /// distance of one. E.g. A[i+1] = A[i] bool isDependenceDistanceOfOne(PredicatedScalarEvolution &PSE, Loop *L) const { @@ -136,7 +137,7 @@ struct StoreToLoadForwardingCandidate { } // end anonymous namespace -/// \brief Check if the store dominates all latches, so as long as there is no +/// Check if the store dominates all latches, so as long as there is no /// intervening store this value will be loaded in the next iteration. static bool doesStoreDominatesAllLatches(BasicBlock *StoreBlock, Loop *L, DominatorTree *DT) { @@ -147,21 +148,21 @@ static bool doesStoreDominatesAllLatches(BasicBlock *StoreBlock, Loop *L, }); } -/// \brief Return true if the load is not executed on all paths in the loop. +/// Return true if the load is not executed on all paths in the loop. static bool isLoadConditional(LoadInst *Load, Loop *L) { return Load->getParent() != L->getHeader(); } namespace { -/// \brief The per-loop class that does most of the work. +/// The per-loop class that does most of the work. class LoadEliminationForLoop { public: LoadEliminationForLoop(Loop *L, LoopInfo *LI, const LoopAccessInfo &LAI, DominatorTree *DT) : L(L), LI(LI), LAI(LAI), DT(DT), PSE(LAI.getPSE()) {} - /// \brief Look through the loop-carried and loop-independent dependences in + /// Look through the loop-carried and loop-independent dependences in /// this loop and find store->load dependences. /// /// Note that no candidate is returned if LAA has failed to analyze the loop @@ -178,7 +179,7 @@ public: // forward and backward dependences qualify. Disqualify loads that have // other unknown dependences. - SmallSet<Instruction *, 4> LoadsWithUnknownDepedence; + SmallPtrSet<Instruction *, 4> LoadsWithUnknownDepedence; for (const auto &Dep : *Deps) { Instruction *Source = Dep.getSource(LAI); @@ -222,14 +223,14 @@ public: return Candidates; } - /// \brief Return the index of the instruction according to program order. + /// Return the index of the instruction according to program order. unsigned getInstrIndex(Instruction *Inst) { auto I = InstOrder.find(Inst); assert(I != InstOrder.end() && "No index for instruction"); return I->second; } - /// \brief If a load has multiple candidates associated (i.e. different + /// If a load has multiple candidates associated (i.e. different /// stores), it means that it could be forwarding from multiple stores /// depending on control flow. Remove these candidates. /// @@ -284,22 +285,24 @@ public: Candidates.remove_if([&](const StoreToLoadForwardingCandidate &Cand) { if (LoadToSingleCand[Cand.Load] != &Cand) { - DEBUG(dbgs() << "Removing from candidates: \n" << Cand - << " The load may have multiple stores forwarding to " - << "it\n"); + LLVM_DEBUG( + dbgs() << "Removing from candidates: \n" + << Cand + << " The load may have multiple stores forwarding to " + << "it\n"); return true; } return false; }); } - /// \brief Given two pointers operations by their RuntimePointerChecking + /// Given two pointers operations by their RuntimePointerChecking /// indices, return true if they require an alias check. /// /// We need a check if one is a pointer for a candidate load and the other is /// a pointer for a possibly intervening store. bool needsChecking(unsigned PtrIdx1, unsigned PtrIdx2, - const SmallSet<Value *, 4> &PtrsWrittenOnFwdingPath, + const SmallPtrSet<Value *, 4> &PtrsWrittenOnFwdingPath, const std::set<Value *> &CandLoadPtrs) { Value *Ptr1 = LAI.getRuntimePointerChecking()->getPointerInfo(PtrIdx1).PointerValue; @@ -309,11 +312,11 @@ public: (PtrsWrittenOnFwdingPath.count(Ptr2) && CandLoadPtrs.count(Ptr1))); } - /// \brief Return pointers that are possibly written to on the path from a + /// Return pointers that are possibly written to on the path from a /// forwarding store to a load. /// /// These pointers need to be alias-checked against the forwarding candidates. - SmallSet<Value *, 4> findPointersWrittenOnForwardingPath( + SmallPtrSet<Value *, 4> findPointersWrittenOnForwardingPath( const SmallVectorImpl<StoreToLoadForwardingCandidate> &Candidates) { // From FirstStore to LastLoad neither of the elimination candidate loads // should overlap with any of the stores. @@ -351,7 +354,7 @@ public: // We're looking for stores after the first forwarding store until the end // of the loop, then from the beginning of the loop until the last // forwarded-to load. Collect the pointer for the stores. - SmallSet<Value *, 4> PtrsWrittenOnFwdingPath; + SmallPtrSet<Value *, 4> PtrsWrittenOnFwdingPath; auto InsertStorePtr = [&](Instruction *I) { if (auto *S = dyn_cast<StoreInst>(I)) @@ -366,16 +369,16 @@ public: return PtrsWrittenOnFwdingPath; } - /// \brief Determine the pointer alias checks to prove that there are no + /// Determine the pointer alias checks to prove that there are no /// intervening stores. SmallVector<RuntimePointerChecking::PointerCheck, 4> collectMemchecks( const SmallVectorImpl<StoreToLoadForwardingCandidate> &Candidates) { - SmallSet<Value *, 4> PtrsWrittenOnFwdingPath = + SmallPtrSet<Value *, 4> PtrsWrittenOnFwdingPath = findPointersWrittenOnForwardingPath(Candidates); // Collect the pointers of the candidate loads. - // FIXME: SmallSet does not work with std::inserter. + // FIXME: SmallPtrSet does not work with std::inserter. std::set<Value *> CandLoadPtrs; transform(Candidates, std::inserter(CandLoadPtrs, CandLoadPtrs.begin()), @@ -394,13 +397,14 @@ public: return false; }); - DEBUG(dbgs() << "\nPointer Checks (count: " << Checks.size() << "):\n"); - DEBUG(LAI.getRuntimePointerChecking()->printChecks(dbgs(), Checks)); + LLVM_DEBUG(dbgs() << "\nPointer Checks (count: " << Checks.size() + << "):\n"); + LLVM_DEBUG(LAI.getRuntimePointerChecking()->printChecks(dbgs(), Checks)); return Checks; } - /// \brief Perform the transformation for a candidate. + /// Perform the transformation for a candidate. void propagateStoredValueToLoadUsers(const StoreToLoadForwardingCandidate &Cand, SCEVExpander &SEE) { @@ -436,11 +440,11 @@ public: Cand.Load->replaceAllUsesWith(PHI); } - /// \brief Top-level driver for each loop: find store->load forwarding + /// Top-level driver for each loop: find store->load forwarding /// candidates, add run-time checks and perform transformation. bool processLoop() { - DEBUG(dbgs() << "\nIn \"" << L->getHeader()->getParent()->getName() - << "\" checking " << *L << "\n"); + LLVM_DEBUG(dbgs() << "\nIn \"" << L->getHeader()->getParent()->getName() + << "\" checking " << *L << "\n"); // Look for store-to-load forwarding cases across the // backedge. E.g.: @@ -479,7 +483,7 @@ public: SmallVector<StoreToLoadForwardingCandidate, 4> Candidates; unsigned NumForwarding = 0; for (const StoreToLoadForwardingCandidate Cand : StoreToLoadDependences) { - DEBUG(dbgs() << "Candidate " << Cand); + LLVM_DEBUG(dbgs() << "Candidate " << Cand); // Make sure that the stored values is available everywhere in the loop in // the next iteration. @@ -498,9 +502,10 @@ public: continue; ++NumForwarding; - DEBUG(dbgs() - << NumForwarding - << ". Valid store-to-load forwarding across the loop backedge\n"); + LLVM_DEBUG( + dbgs() + << NumForwarding + << ". Valid store-to-load forwarding across the loop backedge\n"); Candidates.push_back(Cand); } if (Candidates.empty()) @@ -513,25 +518,26 @@ public: // Too many checks are likely to outweigh the benefits of forwarding. if (Checks.size() > Candidates.size() * CheckPerElim) { - DEBUG(dbgs() << "Too many run-time checks needed.\n"); + LLVM_DEBUG(dbgs() << "Too many run-time checks needed.\n"); return false; } if (LAI.getPSE().getUnionPredicate().getComplexity() > LoadElimSCEVCheckThreshold) { - DEBUG(dbgs() << "Too many SCEV run-time checks needed.\n"); + LLVM_DEBUG(dbgs() << "Too many SCEV run-time checks needed.\n"); return false; } if (!Checks.empty() || !LAI.getPSE().getUnionPredicate().isAlwaysTrue()) { if (L->getHeader()->getParent()->optForSize()) { - DEBUG(dbgs() << "Versioning is needed but not allowed when optimizing " - "for size.\n"); + LLVM_DEBUG( + dbgs() << "Versioning is needed but not allowed when optimizing " + "for size.\n"); return false; } if (!L->isLoopSimplifyForm()) { - DEBUG(dbgs() << "Loop is not is loop-simplify form"); + LLVM_DEBUG(dbgs() << "Loop is not is loop-simplify form"); return false; } @@ -558,7 +564,7 @@ public: private: Loop *L; - /// \brief Maps the load/store instructions to their index according to + /// Maps the load/store instructions to their index according to /// program order. DenseMap<Instruction *, unsigned> InstOrder; @@ -599,7 +605,7 @@ eliminateLoadsAcrossLoops(Function &F, LoopInfo &LI, DominatorTree &DT, namespace { -/// \brief The pass. Most of the work is delegated to the per-loop +/// The pass. Most of the work is delegated to the per-loop /// LoadEliminationForLoop class. class LoopLoadElimination : public FunctionPass { public: |