Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -1528,6 +1528,8 @@ /// The underlying Region. Region &R; + /// The name of the SCoP (identical to the regions name) + std::string name; // Access functions of the SCoP. // @@ -2124,6 +2126,8 @@ /// 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 array_range; @@ -2694,6 +2698,7 @@ 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 { Index: include/polly/ScopPass.h =================================================================== --- include/polly/ScopPass.h +++ include/polly/ScopPass.h @@ -6,24 +6,85 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// // This file defines the ScopPass class. ScopPasses are just RegionPasses, -// except they operate on Polly IR (Scop and ScopStmt) built by ScopInfo Pass. -// Because they operate on Polly IR, not the LLVM IR, ScopPasses are not allowed -// to modify the LLVM IR. Due to this limitation, the ScopPass class takes -// care of declaring that no LLVM passes are invalidated. +// except they operate on Polly IR (Scop and ScopStmt) built by ScopInfo +// Pass. Because they operate on Polly IR, not the LLVM IR, ScopPasses are not +// allowed to modify the LLVM IR. Due to this limitation, the ScopPass class +// takes care of declaring that no LLVM passes are invalidated. // //===----------------------------------------------------------------------===// #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; +struct ScopStandardAnalysisResults; + +using ScopAnalysisManager = AnalysisManager; +using ScopAnalysisManagerFunctionProxy = + InnerAnalysisManagerProxy; +} // namespace polly + +namespace llvm { +using polly::Scop; +using polly::ScopInfo; +using polly::ScopAnalysisManager; +using polly::ScopStandardAnalysisResults; +using polly::ScopAnalysisManagerFunctionProxy; + +template <> +PreservedAnalyses +PassManager::run( + Scop &InitialS, ScopAnalysisManager &AM, ScopStandardAnalysisResults &); +extern template class PassManager; + +template <> class ScopAnalysisManagerFunctionProxy::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 <> +ScopAnalysisManagerFunctionProxy::Result +ScopAnalysisManagerFunctionProxy::run(Function &F, + FunctionAnalysisManager &FAM); +} // namespace llvm + +namespace polly { +using ScopPassManager = + PassManager; /// ScopPass - This class adapts the RegionPass interface to allow convenient /// creation of passes that operate on the Polly IR. Instead of overriding @@ -52,6 +113,57 @@ void print(raw_ostream &OS, const Module *) const override; }; +struct ScopStandardAnalysisResults { + DominatorTree &DT; + ScalarEvolution &SE; + LoopInfo &LI; + RegionInfo &RI; +}; + +template +class FunctionToScopPassAdaptor + : public PassInfoMixin> { +public: + explicit FunctionToScopPassAdaptor(ScopPassT Pass) : Pass(std::move(Pass)) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) { + PreservedAnalyses PA = PreservedAnalyses::all(); + auto &Scops = AM.getResult(F); + if (Scops.empty()) + return PA; + + ScopAnalysisManager &SAM = + AM.getResult(F).getManager(); + + ScopStandardAnalysisResults AR = {AM.getResult(F), + AM.getResult(F), + AM.getResult(F), + AM.getResult(F)}; + + for (auto &S : Scops) { + if (auto *scop = S.second.get()) { + PreservedAnalyses PassPA = Pass.run(*scop, SAM, AR); + + SAM.invalidate(*scop, PassPA); + PA.intersect(std::move(PassPA)); + } + } + + PA.preserveSet>(); + PA.preserve(); + return PA; + } + +private: + ScopPassT Pass; +}; // namespace polly + +template +FunctionToScopPassAdaptor +createFunctionToScopPassAdaptor(ScopPassT Pass) { + return FunctionToScopPassAdaptor(std::move(Pass)); +} + } // namespace polly #endif Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -3213,9 +3213,9 @@ Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI, ScopDetection::DetectionContext &DC) - : SE(&ScalarEvolution), R(R), IsOptimized(false), - HasSingleExitEdge(R.getExitingBlock()), HasErrorBlock(false), - MaxLoopDepth(0), CopyStmtsNum(0), DC(DC), + : SE(&ScalarEvolution), R(R), name("Scop for region " + R.getNameStr()), + IsOptimized(false), HasSingleExitEdge(R.getExitingBlock()), + HasErrorBlock(false), MaxLoopDepth(0), CopyStmtsNum(0), DC(DC), IslCtx(isl_ctx_alloc(), isl_ctx_free), Context(nullptr), Affinator(this, LI), AssumedContext(nullptr), InvalidContext(nullptr), Schedule(nullptr) { Index: lib/Analysis/ScopPass.cpp =================================================================== --- lib/Analysis/ScopPass.cpp +++ lib/Analysis/ScopPass.cpp @@ -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,69 @@ AU.addRequired(); AU.setPreservesAll(); } + +namespace llvm { + +template class PassManager; + +template <> +PreservedAnalyses +PassManager::run( + Scop &S, ScopAnalysisManager &AM, ScopStandardAnalysisResults &AR) { + auto PA = PreservedAnalyses::all(); + for (auto &Pass : Passes) { + auto PassPA = Pass->run(S, AM, AR); + + AM.invalidate(S, PassPA); + PA.intersect(std::move(PassPA)); + } + + // All analyses for 'this' Scop have been invalidated above. Different Scops + // aren't affected + // FIXME is this correct wrt. the current pass behaviours? + PA.preserveSet>(); + 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(); + if (!(PAC.preserved() || PAC.preservedSet>() || + Inv.invalidate(F, PA) || + Inv.invalidate(F, PA) || + Inv.invalidate(F, PA) || + Inv.invalidate(F, PA) || + Inv.invalidate(F, PA) || + Inv.invalidate(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. + } + + // FIXME What about deferred invalidation? + + if (PA.allAnalysesInSetPreserved>()) + for (auto &S : *SI) + if (auto *scop = S.second.get()) + 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(F)); +} +} // namespace llvm