[polly] r303062 - [Polly][NewPM][WIP] Add a ScopPassManager

Philip Pfaffe via llvm-commits llvm-commits at lists.llvm.org
Mon May 15 06:43:02 PDT 2017


Author: pfaffe
Date: Mon May 15 08:43:01 2017
New Revision: 303062

URL: http://llvm.org/viewvc/llvm-project?rev=303062&view=rev
Log:
[Polly][NewPM][WIP] Add a ScopPassManager

This patch adds both a ScopAnalysisManager and a ScopPassManager.

The ScopAnalysisManager is itself a Function-Analysis, and manages
analyses on Scops. The ScopPassManager takes care of building Scop pass
pipelines.

This patch is marked WIP because I've left two FIXMEs which I need to
think about some more. Both of these deal with invalidation:

Deferred invalidation is currently not implemented. Deferred
invalidation deals with analyses which cache references to other
analysis results. If these results are invalidated, invalidation needs
to be propagated into the caching analyses.
The ScopPassManager as implemented assumes that ScopPasses do not affect
other Scops in any way. There has been some discussion about this on
other patch threads, however it makes sense to reiterate this for this
specific patch.
I'm uploading this patch even though it's incomplete to encourage
discussion and give you an impression of how this is going to work.

Differential Revision: https://reviews.llvm.org/D33192

Modified:
    polly/trunk/include/polly/ScopInfo.h
    polly/trunk/include/polly/ScopPass.h
    polly/trunk/lib/Analysis/ScopInfo.cpp
    polly/trunk/lib/Analysis/ScopPass.cpp
    polly/trunk/unittests/CMakeLists.txt

Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=303062&r1=303061&r2=303062&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Mon May 15 08:43:01 2017
@@ -1572,6 +1572,9 @@ private:
   /// The underlying Region.
   Region &R;
 
+  /// The name of the SCoP (identical to the regions name)
+  std::string name;
+
   // Access functions of the SCoP.
   //
   // This owns all the MemoryAccess objects of the Scop created in this pass.
@@ -2201,6 +2204,8 @@ public:
   /// could be executed.
   bool isEmpty() const { return Stmts.empty(); }
 
+  const StringRef getName() const { return name; }
+
   typedef ArrayInfoSetTy::iterator array_iterator;
   typedef ArrayInfoSetTy::const_iterator const_array_iterator;
   typedef iterator_range<ArrayInfoSetTy::iterator> array_range;
@@ -2795,6 +2800,7 @@ public:
   iterator end() { return RegionToScopMap.end(); }
   const_iterator begin() const { return RegionToScopMap.begin(); }
   const_iterator end() const { return RegionToScopMap.end(); }
+  bool empty() const { return RegionToScopMap.empty(); }
 };
 
 struct ScopInfoAnalysis : public AnalysisInfoMixin<ScopInfoAnalysis> {

Modified: polly/trunk/include/polly/ScopPass.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopPass.h?rev=303062&r1=303061&r2=303062&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopPass.h (original)
+++ polly/trunk/include/polly/ScopPass.h Mon May 15 08:43:01 2017
@@ -18,12 +18,86 @@
 #ifndef POLLY_SCOP_PASS_H
 #define POLLY_SCOP_PASS_H
 
+#include "polly/ScopInfo.h"
+#include "llvm/ADT/PriorityWorklist.h"
 #include "llvm/Analysis/RegionPass.h"
+#include "llvm/IR/PassManager.h"
 
 using namespace llvm;
 
 namespace polly {
 class Scop;
+class SPMUpdater;
+struct ScopStandardAnalysisResults;
+
+using ScopAnalysisManager =
+    AnalysisManager<Scop, ScopStandardAnalysisResults &>;
+using ScopAnalysisManagerFunctionProxy =
+    InnerAnalysisManagerProxy<ScopAnalysisManager, Function>;
+using FunctionAnalysisManagerScopProxy =
+    OuterAnalysisManagerProxy<FunctionAnalysisManager, Scop,
+                              ScopStandardAnalysisResults &>;
+} // namespace polly
+
+namespace llvm {
+using polly::Scop;
+using polly::ScopInfo;
+using polly::ScopAnalysisManager;
+using polly::ScopStandardAnalysisResults;
+using polly::ScopAnalysisManagerFunctionProxy;
+using polly::SPMUpdater;
+
+template <>
+class InnerAnalysisManagerProxy<ScopAnalysisManager, Function>::Result {
+public:
+  explicit Result(ScopAnalysisManager &InnerAM, ScopInfo &SI)
+      : InnerAM(&InnerAM), SI(&SI) {}
+  Result(Result &&R) : InnerAM(std::move(R.InnerAM)), SI(R.SI) {
+    R.InnerAM = nullptr;
+  }
+  Result &operator=(Result &&RHS) {
+    InnerAM = RHS.InnerAM;
+    SI = RHS.SI;
+    RHS.InnerAM = nullptr;
+    return *this;
+  }
+  ~Result() {
+    if (!InnerAM)
+      return;
+    InnerAM->clear();
+  }
+
+  ScopAnalysisManager &getManager() { return *InnerAM; }
+
+  bool invalidate(Function &F, const PreservedAnalyses &PA,
+                  FunctionAnalysisManager::Invalidator &Inv);
+
+private:
+  ScopAnalysisManager *InnerAM;
+  ScopInfo *SI;
+};
+
+template <>
+InnerAnalysisManagerProxy<ScopAnalysisManager, Function>::Result
+InnerAnalysisManagerProxy<ScopAnalysisManager, Function>::run(
+    Function &F, FunctionAnalysisManager &FAM);
+
+template <>
+PreservedAnalyses
+PassManager<Scop, ScopAnalysisManager, ScopStandardAnalysisResults &,
+            SPMUpdater &>::run(Scop &InitialS, ScopAnalysisManager &AM,
+                               ScopStandardAnalysisResults &, SPMUpdater &);
+extern template class PassManager<Scop, ScopAnalysisManager,
+                                  ScopStandardAnalysisResults &, SPMUpdater &>;
+extern template class InnerAnalysisManagerProxy<ScopAnalysisManager, Function>;
+extern template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Scop,
+                                                ScopStandardAnalysisResults &>;
+} // namespace llvm
+
+namespace polly {
+using ScopPassManager =
+    PassManager<Scop, ScopAnalysisManager, ScopStandardAnalysisResults &,
+                SPMUpdater &>;
 
 /// ScopPass - This class adapts the RegionPass interface to allow convenient
 /// creation of passes that operate on the Polly IR. Instead of overriding
@@ -52,6 +126,79 @@ private:
   void print(raw_ostream &OS, const Module *) const override;
 };
 
+struct ScopStandardAnalysisResults {
+  DominatorTree &DT;
+  ScalarEvolution &SE;
+  LoopInfo &LI;
+  RegionInfo &RI;
+};
+
+class SPMUpdater {
+public:
+  SPMUpdater(SmallPriorityWorklist<Scop *, 4> &Worklist,
+             ScopAnalysisManager &SAM)
+      : Worklist(Worklist), SAM(SAM) {}
+
+  void SkipScop(Scop &S) {
+    if (Worklist.erase(&S))
+      SAM.clear(S);
+  }
+
+private:
+  SmallPriorityWorklist<Scop *, 4> &Worklist;
+  ScopAnalysisManager &SAM;
+};
+
+template <typename ScopPassT>
+class FunctionToScopPassAdaptor
+    : public PassInfoMixin<FunctionToScopPassAdaptor<ScopPassT>> {
+public:
+  explicit FunctionToScopPassAdaptor(ScopPassT Pass) : Pass(std::move(Pass)) {}
+
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
+    PreservedAnalyses PA = PreservedAnalyses::all();
+    auto &Scops = AM.getResult<ScopInfoAnalysis>(F);
+    if (Scops.empty())
+      return PA;
+
+    ScopAnalysisManager &SAM =
+        AM.getResult<ScopAnalysisManagerFunctionProxy>(F).getManager();
+
+    ScopStandardAnalysisResults AR = {AM.getResult<DominatorTreeAnalysis>(F),
+                                      AM.getResult<ScalarEvolutionAnalysis>(F),
+                                      AM.getResult<LoopAnalysis>(F),
+                                      AM.getResult<RegionInfoAnalysis>(F)};
+
+    SmallPriorityWorklist<Scop *, 4> Worklist;
+    SPMUpdater Updater{Worklist, SAM};
+
+    for (auto &S : Scops)
+      if (auto *scop = S.second.get())
+        Worklist.insert(scop);
+
+    while (!Worklist.empty()) {
+      Scop *scop = Worklist.pop_back_val();
+      PreservedAnalyses PassPA = Pass.run(*scop, SAM, AR, Updater);
+
+      SAM.invalidate(*scop, PassPA);
+      PA.intersect(std::move(PassPA));
+    };
+
+    PA.preserveSet<AllAnalysesOn<Scop>>();
+    PA.preserve<ScopAnalysisManagerFunctionProxy>();
+    return PA;
+  }
+
+private:
+  ScopPassT Pass;
+}; // namespace polly
+
+template <typename ScopPassT>
+FunctionToScopPassAdaptor<ScopPassT>
+createFunctionToScopPassAdaptor(ScopPassT Pass) {
+  return FunctionToScopPassAdaptor<ScopPassT>(std::move(Pass));
+}
+
 } // namespace polly
 
 #endif

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=303062&r1=303061&r2=303062&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Mon May 15 08:43:01 2017
@@ -3279,7 +3279,7 @@ static Loop *getLoopSurroundingScop(Scop
 
 Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI,
            ScopDetection::DetectionContext &DC)
-    : SE(&ScalarEvolution), R(R), IsOptimized(false),
+    : SE(&ScalarEvolution), R(R), name(R.getNameStr()), IsOptimized(false),
       HasSingleExitEdge(R.getExitingBlock()), HasErrorBlock(false),
       MaxLoopDepth(0), CopyStmtsNum(0), DC(DC),
       IslCtx(isl_ctx_alloc(), isl_ctx_free), Context(nullptr),

Modified: polly/trunk/lib/Analysis/ScopPass.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopPass.cpp?rev=303062&r1=303061&r2=303062&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopPass.cpp (original)
+++ polly/trunk/lib/Analysis/ScopPass.cpp Mon May 15 08:43:01 2017
@@ -14,6 +14,8 @@
 #include "polly/ScopPass.h"
 #include "polly/ScopInfo.h"
 
+#include "llvm/Analysis/AssumptionCache.h"
+
 using namespace llvm;
 using namespace polly;
 
@@ -35,3 +37,101 @@ void ScopPass::getAnalysisUsage(Analysis
   AU.addRequired<ScopInfoRegionPass>();
   AU.setPreservesAll();
 }
+
+namespace llvm {
+
+template class PassManager<Scop, ScopAnalysisManager,
+                           ScopStandardAnalysisResults &, SPMUpdater &>;
+template class InnerAnalysisManagerProxy<ScopAnalysisManager, Function>;
+template class OuterAnalysisManagerProxy<FunctionAnalysisManager, Scop,
+                                         ScopStandardAnalysisResults &>;
+
+template <>
+PreservedAnalyses
+PassManager<Scop, ScopAnalysisManager, ScopStandardAnalysisResults &,
+            SPMUpdater &>::run(Scop &S, ScopAnalysisManager &AM,
+                               ScopStandardAnalysisResults &AR, SPMUpdater &U) {
+  auto PA = PreservedAnalyses::all();
+  for (auto &Pass : Passes) {
+    auto PassPA = Pass->run(S, AM, AR, U);
+
+    AM.invalidate(S, PassPA);
+    PA.intersect(std::move(PassPA));
+  }
+
+  // All analyses for 'this' Scop have been invalidated above.
+  // If ScopPasses affect break other scops they have to propagate this
+  // information through the updater
+  PA.preserveSet<AllAnalysesOn<Scop>>();
+  return PA;
+}
+
+bool ScopAnalysisManagerFunctionProxy::Result::invalidate(
+    Function &F, const PreservedAnalyses &PA,
+    FunctionAnalysisManager::Invalidator &Inv) {
+
+  // First, check whether our ScopInfo is about to be invalidated
+  auto PAC = PA.getChecker<ScopAnalysisManagerFunctionProxy>();
+  if (!(PAC.preserved() || PAC.preservedSet<AllAnalysesOn<Function>>() ||
+        Inv.invalidate<ScopAnalysis>(F, PA) ||
+        Inv.invalidate<ScalarEvolutionAnalysis>(F, PA) ||
+        Inv.invalidate<LoopAnalysis>(F, PA) ||
+        Inv.invalidate<AAManager>(F, PA) ||
+        Inv.invalidate<DominatorTreeAnalysis>(F, PA) ||
+        Inv.invalidate<AssumptionAnalysis>(F, PA))) {
+
+    // As everything depends on ScopInfo, we must drop all existing results
+    for (auto &S : *SI)
+      if (auto *scop = S.second.get())
+        if (InnerAM)
+          InnerAM->clear(*scop);
+
+    InnerAM = nullptr;
+    return true; // Invalidate the proxy result as well.
+  }
+
+  bool allPreserved = PA.allAnalysesInSetPreserved<AllAnalysesOn<Scop>>();
+
+  // Invalidate all non-preserved analyses
+  // Even if all analyses were preserved, we still need to run deferred
+  // invalidation
+  for (auto &S : *SI) {
+    Optional<PreservedAnalyses> InnerPA;
+    auto *scop = S.second.get();
+    if (!scop)
+      continue;
+
+    if (auto *OuterProxy =
+            InnerAM->getCachedResult<FunctionAnalysisManagerScopProxy>(*scop)) {
+      for (const auto &InvPair : OuterProxy->getOuterInvalidations()) {
+        auto *OuterAnalysisID = InvPair.first;
+        const auto &InnerAnalysisIDs = InvPair.second;
+
+        if (Inv.invalidate(OuterAnalysisID, F, PA)) {
+          if (!InnerPA)
+            InnerPA = PA;
+          for (auto *InnerAnalysisID : InnerAnalysisIDs)
+            InnerPA->abandon(InnerAnalysisID);
+        }
+      }
+
+      if (InnerPA) {
+        InnerAM->invalidate(*scop, *InnerPA);
+        continue;
+      }
+    }
+
+    if (!allPreserved)
+      InnerAM->invalidate(*scop, PA);
+  }
+
+  return false; // This proxy is still valid
+}
+
+template <>
+ScopAnalysisManagerFunctionProxy::Result
+ScopAnalysisManagerFunctionProxy::run(Function &F,
+                                      FunctionAnalysisManager &FAM) {
+  return Result(*InnerAM, FAM.getResult<ScopInfoAnalysis>(F));
+}
+} // namespace llvm

Modified: polly/trunk/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/unittests/CMakeLists.txt?rev=303062&r1=303061&r2=303062&view=diff
==============================================================================
--- polly/trunk/unittests/CMakeLists.txt (original)
+++ polly/trunk/unittests/CMakeLists.txt Mon May 15 08:43:01 2017
@@ -22,3 +22,4 @@ endfunction()
 add_subdirectory(Isl)
 add_subdirectory(Flatten)
 add_subdirectory(DeLICM)
+add_subdirectory(ScopPassManager)




More information about the llvm-commits mailing list