From 8c60b4112dcb5fd1ec8960798b9e3f5111ddbf1c Mon Sep 17 00:00:00 2001 From: Xinliang David Li Date: Wed, 8 Jun 2016 20:15:37 +0000 Subject: [PATCH] [PM] Refector LoopAccessInfo analysis code This is the preparation patch to port the analysis to new PM Differential Revision: http://reviews.llvm.org/D20560 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@272194 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/LoopAccessAnalysis.h | 66 +++++++++++++++++++-------- lib/Analysis/LoopAccessAnalysis.cpp | 23 +++++----- lib/Transforms/Scalar/LoopDistribute.cpp | 2 +- lib/Transforms/Scalar/LoopLoadElimination.cpp | 2 +- lib/Transforms/Scalar/LoopVersioningLICM.cpp | 2 +- lib/Transforms/Utils/LoopVersioning.cpp | 2 +- lib/Transforms/Vectorize/LoopVectorize.cpp | 2 +- 7 files changed, 62 insertions(+), 37 deletions(-) diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index 795f4cd746d..71d81b5b782 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -670,10 +670,48 @@ int getPtrStride(PredicatedScalarEvolution &PSE, Value *Ptr, const Loop *Lp, bool Assume = false); /// \brief Returns true if the memory operations \p A and \p B are consecutive. -/// This is a simple API that does not depend on the analysis pass. +/// This is a simple API that does not depend on the analysis pass. bool isConsecutiveAccess(Value *A, Value *B, const DataLayout &DL, ScalarEvolution &SE, bool CheckType = true); +/// \brief This class holds the result of LoopAccessAnalysis pass. +class LoopAccessAnalysisResult { +public: + void setDepAnalyses(AliasAnalysis *AA, DominatorTree *DT, LoopInfo *LI, + ScalarEvolution *SCEV, TargetLibraryInfo *TLI) { + this->AA = AA; + this->DT = DT; + this->LI = LI; + this->SCEV = SCEV; + this->TLI = TLI; + } + /// \brief Query the result of the loop access information for the loop \p L. + /// + /// If the client speculates (and then issues run-time checks) for the values + /// of symbolic strides, \p Strides provides the mapping (see + /// replaceSymbolicStrideSCEV). If there is no cached result available run + /// the analysis. + const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides); + + void print(raw_ostream &OS, const Module *M = nullptr) const; + + /// \brief Invalidate the cache when the pass is freed. + void releaseMemory() { + LoopAccessInfoMap.clear(); + } + +private: + /// \brief LoopAccessInfo is created on demand. This map caches + /// the computed results. + DenseMap> LoopAccessInfoMap; + + AliasAnalysis *AA = nullptr; + DominatorTree *DT = nullptr; + LoopInfo *LI = nullptr; + ScalarEvolution *SCEV = nullptr; + TargetLibraryInfo *TLI = nullptr; +}; + /// \brief This analysis provides dependence information for the memory accesses /// of a loop. /// @@ -685,7 +723,7 @@ class LoopAccessAnalysis : public FunctionPass { public: static char ID; - LoopAccessAnalysis() : FunctionPass(ID) { + LoopAccessAnalysis() : FunctionPass(ID), LAAR() { initializeLoopAccessAnalysisPass(*PassRegistry::getPassRegistry()); } @@ -693,32 +731,20 @@ public: void getAnalysisUsage(AnalysisUsage &AU) const override; - /// \brief Query the result of the loop access information for the loop \p L. - /// - /// If the client speculates (and then issues run-time checks) for the values - /// of symbolic strides, \p Strides provides the mapping (see - /// replaceSymbolicStrideSCEV). If there is no cached result available run - /// the analysis. - const LoopAccessInfo &getInfo(Loop *L, const ValueToValueMap &Strides); + LoopAccessAnalysisResult &getResult() { return LAAR; } void releaseMemory() override { // Invalidate the cache when the pass is freed. - LoopAccessInfoMap.clear(); + LAAR.releaseMemory(); } /// \brief Print the result of the analysis when invoked with -analyze. - void print(raw_ostream &OS, const Module *M = nullptr) const override; + void print(raw_ostream &OS, const Module *M = nullptr) const override { + LAAR.print(OS, M); + } private: - /// \brief The cache. - DenseMap> LoopAccessInfoMap; - - // The used analysis passes. - ScalarEvolution *SE; - const TargetLibraryInfo *TLI; - AliasAnalysis *AA; - DominatorTree *DT; - LoopInfo *LI; + LoopAccessAnalysisResult LAAR; }; inline Instruction *MemoryDepChecker::Dependence::getSource( diff --git a/lib/Analysis/LoopAccessAnalysis.cpp b/lib/Analysis/LoopAccessAnalysis.cpp index ff5bc595da5..23e913a07bb 100644 --- a/lib/Analysis/LoopAccessAnalysis.cpp +++ b/lib/Analysis/LoopAccessAnalysis.cpp @@ -1932,7 +1932,7 @@ void LoopAccessInfo::print(raw_ostream &OS, unsigned Depth) const { } const LoopAccessInfo & -LoopAccessAnalysis::getInfo(Loop *L, const ValueToValueMap &Strides) { +LoopAccessAnalysisResult::getInfo(Loop *L, const ValueToValueMap &Strides) { auto &LAI = LoopAccessInfoMap[L]; #ifndef NDEBUG @@ -1942,8 +1942,8 @@ LoopAccessAnalysis::getInfo(Loop *L, const ValueToValueMap &Strides) { if (!LAI) { const DataLayout &DL = L->getHeader()->getModule()->getDataLayout(); - LAI = - llvm::make_unique(L, SE, DL, TLI, AA, DT, LI, Strides); + LAI = llvm::make_unique(L, SCEV, DL, TLI, AA, DT, LI, + Strides); #ifndef NDEBUG LAI->NumSymbolicStrides = Strides.size(); #endif @@ -1951,26 +1951,25 @@ LoopAccessAnalysis::getInfo(Loop *L, const ValueToValueMap &Strides) { return *LAI.get(); } -void LoopAccessAnalysis::print(raw_ostream &OS, const Module *M) const { - LoopAccessAnalysis &LAA = *const_cast(this); - +void LoopAccessAnalysisResult::print(raw_ostream &OS, const Module *M) const { ValueToValueMap NoSymbolicStrides; for (Loop *TopLevelLoop : *LI) for (Loop *L : depth_first(TopLevelLoop)) { OS.indent(2) << L->getHeader()->getName() << ":\n"; - auto &LAI = LAA.getInfo(L, NoSymbolicStrides); + auto &LAI = const_cast(this)->getInfo( + L, NoSymbolicStrides); LAI.print(OS, 4); } } bool LoopAccessAnalysis::runOnFunction(Function &F) { - SE = &getAnalysis().getSE(); auto *TLIP = getAnalysisIfAvailable(); - TLI = TLIP ? &TLIP->getTLI() : nullptr; - AA = &getAnalysis().getAAResults(); - DT = &getAnalysis().getDomTree(); - LI = &getAnalysis().getLoopInfo(); + LAAR.setDepAnalyses(&getAnalysis().getAAResults(), + &getAnalysis().getDomTree(), + &getAnalysis().getLoopInfo(), + &getAnalysis().getSE(), + TLIP ? &TLIP->getTLI() : nullptr); return false; } diff --git a/lib/Transforms/Scalar/LoopDistribute.cpp b/lib/Transforms/Scalar/LoopDistribute.cpp index 48405a2b721..3d82eb82482 100644 --- a/lib/Transforms/Scalar/LoopDistribute.cpp +++ b/lib/Transforms/Scalar/LoopDistribute.cpp @@ -608,7 +608,7 @@ public: return fail("multiple exit blocks"); // LAA will check that we only have a single exiting block. - LAI = &LAA->getInfo(L, ValueToValueMap()); + LAI = &LAA->getResult().getInfo(L, ValueToValueMap()); // Currently, we only distribute to isolate the part of the loop with // dependence cycles to enable partial vectorization. diff --git a/lib/Transforms/Scalar/LoopLoadElimination.cpp b/lib/Transforms/Scalar/LoopLoadElimination.cpp index 8f2b3acabb6..32c0bd63a4b 100644 --- a/lib/Transforms/Scalar/LoopLoadElimination.cpp +++ b/lib/Transforms/Scalar/LoopLoadElimination.cpp @@ -552,7 +552,7 @@ public: // Now walk the identified inner loops. bool Changed = false; for (Loop *L : Worklist) { - const LoopAccessInfo &LAI = LAA->getInfo(L, ValueToValueMap()); + const LoopAccessInfo &LAI = LAA->getResult().getInfo(L, ValueToValueMap()); // The actual work is performed by LoadEliminationForLoop. LoadEliminationForLoop LEL(L, LI, LAI, DT); Changed |= LEL.processLoop(); diff --git a/lib/Transforms/Scalar/LoopVersioningLICM.cpp b/lib/Transforms/Scalar/LoopVersioningLICM.cpp index 7ccf2271e62..dab4ba16714 100644 --- a/lib/Transforms/Scalar/LoopVersioningLICM.cpp +++ b/lib/Transforms/Scalar/LoopVersioningLICM.cpp @@ -411,7 +411,7 @@ bool LoopVersioningLICM::legalLoopInstructions() { return false; } // Get LoopAccessInfo from current loop. - LAI = &LAA->getInfo(CurLoop, Strides); + LAI = &LAA->getResult().getInfo(CurLoop, Strides); // Check LoopAccessInfo for need of runtime check. if (LAI->getRuntimePointerChecking()->getChecks().empty()) { DEBUG(dbgs() << " LAA: Runtime check not found !!\n"); diff --git a/lib/Transforms/Utils/LoopVersioning.cpp b/lib/Transforms/Utils/LoopVersioning.cpp index 736d79ad81c..3e677d8ad53 100644 --- a/lib/Transforms/Utils/LoopVersioning.cpp +++ b/lib/Transforms/Utils/LoopVersioning.cpp @@ -268,7 +268,7 @@ public: // Now walk the identified inner loops. bool Changed = false; for (Loop *L : Worklist) { - const LoopAccessInfo &LAI = LAA->getInfo(L, ValueToValueMap()); + const LoopAccessInfo &LAI = LAA->getResult().getInfo(L, ValueToValueMap()); if (LAI.getNumRuntimePointerChecks() || !LAI.PSE.getUnionPredicate().isAlwaysTrue()) { LoopVersioning LVer(LAI, L, LI, DT, SE); diff --git a/lib/Transforms/Vectorize/LoopVectorize.cpp b/lib/Transforms/Vectorize/LoopVectorize.cpp index 144eab58f74..78ea58cf499 100644 --- a/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -4931,7 +4931,7 @@ void LoopVectorizationLegality::collectLoopUniforms() { } bool LoopVectorizationLegality::canVectorizeMemory() { - LAI = &LAA->getInfo(TheLoop, Strides); + LAI = &LAA->getResult().getInfo(TheLoop, Strides); auto &OptionalReport = LAI->getReport(); if (OptionalReport) emitAnalysis(VectorizationReport(*OptionalReport)); -- 2.11.0