//===--------- ScopPass.h - Pass for Static Control Parts --------*-C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // 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. // //===----------------------------------------------------------------------===// #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" #include "llvm/IR/PassManagerImpl.h" using namespace llvm; namespace polly { class Scop; class SPMUpdater; struct ScopStandardAnalysisResults; using ScopAnalysisManager = AnalysisManager; using ScopAnalysisManagerFunctionProxy = InnerAnalysisManagerProxy; using FunctionAnalysisManagerScopProxy = OuterAnalysisManagerProxy; } // namespace polly namespace llvm { using polly::Scop; using polly::ScopAnalysisManager; using polly::ScopAnalysisManagerFunctionProxy; using polly::ScopInfo; using polly::ScopStandardAnalysisResults; using polly::SPMUpdater; template <> class InnerAnalysisManagerProxy::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; }; // A partial specialization of the require analysis template pass to handle // extra parameters template struct RequireAnalysisPass : PassInfoMixin< RequireAnalysisPass> { PreservedAnalyses run(Scop &L, ScopAnalysisManager &AM, ScopStandardAnalysisResults &AR, SPMUpdater &) { (void)AM.template getResult(L, AR); return PreservedAnalyses::all(); } }; template <> InnerAnalysisManagerProxy::Result InnerAnalysisManagerProxy::run( Function &F, FunctionAnalysisManager &FAM); template <> PreservedAnalyses PassManager::run(Scop &InitialS, ScopAnalysisManager &AM, ScopStandardAnalysisResults &, SPMUpdater &); extern template class PassManager; extern template class InnerAnalysisManagerProxy; extern template class OuterAnalysisManagerProxy; } // namespace llvm namespace polly { template class OwningInnerAnalysisManagerProxy : public InnerAnalysisManagerProxy { public: OwningInnerAnalysisManagerProxy() : InnerAnalysisManagerProxy(InnerAM) {} using Result = typename InnerAnalysisManagerProxy::Result; Result run(IRUnitT &IR, AnalysisManager &AM, ExtraArgTs...) { return Result(InnerAM); } AnalysisManagerT &getManager() { return InnerAM; } private: AnalysisManagerT InnerAM; }; template <> OwningInnerAnalysisManagerProxy::Result OwningInnerAnalysisManagerProxy::run( Function &F, FunctionAnalysisManager &FAM); extern template class OwningInnerAnalysisManagerProxy; using OwningScopAnalysisManagerFunctionProxy = OwningInnerAnalysisManagerProxy; 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 /// runOnRegion, subclasses override runOnScop. class ScopPass : public RegionPass { Scop *S; protected: explicit ScopPass(char &ID) : RegionPass(ID), S(0) {} /// runOnScop - This method must be overloaded to perform the /// desired Polyhedral transformation or analysis. /// virtual bool runOnScop(Scop &S) = 0; /// Print method for SCoPs. virtual void printScop(raw_ostream &OS, Scop &S) const {} /// getAnalysisUsage - Subclasses that override getAnalysisUsage /// must call this. /// virtual void getAnalysisUsage(AnalysisUsage &AU) const override; private: bool runOnRegion(Region *R, RGPassManager &RGM) override; void print(raw_ostream &OS, const Module *) const override; }; struct ScopStandardAnalysisResults { DominatorTree &DT; ScopInfo &SI; ScalarEvolution &SE; LoopInfo &LI; RegionInfo &RI; }; class SPMUpdater { public: SPMUpdater(SmallPriorityWorklist &Worklist, ScopAnalysisManager &SAM) : InvalidateCurrentScop(false), Worklist(Worklist), SAM(SAM) {} bool invalidateCurrentScop() const { return InvalidateCurrentScop; } void invalidateScop(Scop &S) { if (&S == CurrentScop) InvalidateCurrentScop = true; Worklist.erase(&S.getRegion()); SAM.clear(S, S.getName()); } private: Scop *CurrentScop; bool InvalidateCurrentScop; SmallPriorityWorklist &Worklist; ScopAnalysisManager &SAM; template friend class FunctionToScopPassAdaptor; }; 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 &SD = AM.getResult(F); auto &SI = AM.getResult(F); if (SI.empty()) return PA; SmallPriorityWorklist Worklist; for (auto &S : SI) if (S.second) Worklist.insert(S.first); ScopStandardAnalysisResults AR = {AM.getResult(F), AM.getResult(F), AM.getResult(F), AM.getResult(F), AM.getResult(F)}; ScopAnalysisManager &SAM = AM.getResult(F).getManager(); SPMUpdater Updater{Worklist, SAM}; while (!Worklist.empty()) { Region *R = Worklist.pop_back_val(); if (!SD.isMaxRegionInScop(*R)) continue; Scop *scop = SI.getScop(R); if (!scop) continue; Updater.CurrentScop = scop; Updater.InvalidateCurrentScop = false; PreservedAnalyses PassPA = Pass.run(*scop, SAM, AR, Updater); SAM.invalidate(*scop, PassPA); PA.intersect(std::move(PassPA)); if (Updater.invalidateCurrentScop()) SI.recompute(); }; PA.preserveSet>(); PA.preserve(); PA.preserve(); PA.preserve(); PA.preserve(); PA.preserve(); PA.preserve(); PA.preserve(); return PA; } private: ScopPassT Pass; }; template FunctionToScopPassAdaptor createFunctionToScopPassAdaptor(ScopPassT Pass) { return FunctionToScopPassAdaptor(std::move(Pass)); } } // namespace polly #endif