| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- //===--------- 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/Analysis/TargetTransformInfo.h"
- #include "llvm/IR/PassManager.h"
- #include "llvm/IR/PassManagerImpl.h"
- namespace polly {
- using llvm::AllAnalysesOn;
- using llvm::AnalysisManager;
- using llvm::DominatorTreeAnalysis;
- using llvm::InnerAnalysisManagerProxy;
- using llvm::LoopAnalysis;
- using llvm::OuterAnalysisManagerProxy;
- using llvm::PassManager;
- using llvm::RegionInfoAnalysis;
- using llvm::ScalarEvolutionAnalysis;
- using llvm::SmallPriorityWorklist;
- using llvm::TargetIRAnalysis;
- using llvm::TargetTransformInfo;
- 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::ScopAnalysisManager;
- using polly::ScopAnalysisManagerFunctionProxy;
- using polly::ScopInfo;
- using polly::ScopStandardAnalysisResults;
- 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;
- };
- // A partial specialization of the require analysis template pass to handle
- // extra parameters
- template <typename AnalysisT>
- struct RequireAnalysisPass<AnalysisT, Scop, ScopAnalysisManager,
- ScopStandardAnalysisResults &, SPMUpdater &>
- : PassInfoMixin<
- RequireAnalysisPass<AnalysisT, Scop, ScopAnalysisManager,
- ScopStandardAnalysisResults &, SPMUpdater &>> {
- PreservedAnalyses run(Scop &L, ScopAnalysisManager &AM,
- ScopStandardAnalysisResults &AR, SPMUpdater &) {
- (void)AM.template getResult<AnalysisT>(L, AR);
- return PreservedAnalyses::all();
- }
- };
- 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 {
- template <typename AnalysisManagerT, typename IRUnitT, typename... ExtraArgTs>
- class OwningInnerAnalysisManagerProxy
- : public InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT> {
- public:
- OwningInnerAnalysisManagerProxy()
- : InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT>(InnerAM) {}
- using Result = typename InnerAnalysisManagerProxy<AnalysisManagerT, IRUnitT,
- ExtraArgTs...>::Result;
- Result run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
- ExtraArgTs...) {
- return Result(InnerAM);
- }
- AnalysisManagerT &getManager() { return InnerAM; }
- private:
- AnalysisManagerT InnerAM;
- };
- template <>
- OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>::Result
- OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>::run(
- Function &F, FunctionAnalysisManager &FAM);
- extern template class OwningInnerAnalysisManagerProxy<ScopAnalysisManager,
- Function>;
- using OwningScopAnalysisManagerFunctionProxy =
- OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>;
- 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
- /// 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;
- TargetTransformInfo &TTI;
- };
- class SPMUpdater {
- public:
- SPMUpdater(SmallPriorityWorklist<Region *, 4> &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<Region *, 4> &Worklist;
- ScopAnalysisManager &SAM;
- template <typename ScopPassT> friend class FunctionToScopPassAdaptor;
- };
- template <typename ScopPassT>
- class FunctionToScopPassAdaptor
- : public PassInfoMixin<FunctionToScopPassAdaptor<ScopPassT>> {
- public:
- explicit FunctionToScopPassAdaptor(ScopPassT Pass) : Pass(std::move(Pass)) {}
- PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM) {
- ScopDetection &SD = AM.getResult<ScopAnalysis>(F);
- ScopInfo &SI = AM.getResult<ScopInfoAnalysis>(F);
- if (SI.empty()) {
- // With no scops having been detected, no IR changes have been made and
- // therefore all analyses are preserved. However, we must still free the
- // Scop analysis results which may hold AssertingVH that cause an error
- // if its value is destroyed.
- PreservedAnalyses PA = PreservedAnalyses::all();
- PA.abandon<ScopInfoAnalysis>();
- PA.abandon<ScopAnalysis>();
- AM.invalidate(F, PA);
- return PreservedAnalyses::all();
- }
- SmallPriorityWorklist<Region *, 4> Worklist;
- for (auto &S : SI)
- if (S.second)
- Worklist.insert(S.first);
- ScopStandardAnalysisResults AR = {AM.getResult<DominatorTreeAnalysis>(F),
- AM.getResult<ScopInfoAnalysis>(F),
- AM.getResult<ScalarEvolutionAnalysis>(F),
- AM.getResult<LoopAnalysis>(F),
- AM.getResult<RegionInfoAnalysis>(F),
- AM.getResult<TargetIRAnalysis>(F)};
- ScopAnalysisManager &SAM =
- AM.getResult<ScopAnalysisManagerFunctionProxy>(F).getManager();
- SPMUpdater Updater{Worklist, SAM};
- while (!Worklist.empty()) {
- Region *R = Worklist.pop_back_val();
- if (!SD.isMaxRegionInScop(*R, /*Verifying=*/false))
- 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);
- if (Updater.invalidateCurrentScop())
- SI.recompute();
- };
- // FIXME: For the same reason as we add a BarrierNoopPass in the legacy pass
- // manager, do not preserve any analyses. While CodeGeneration may preserve
- // IR analyses sufficiently to process another Scop in the same function (it
- // has to, otherwise the ScopDetection result itself would need to be
- // invalidated), it is not sufficient for other purposes. For instance,
- // CodeGeneration does not inform LoopInfo about new loops in the
- // Polly-generated IR.
- return PreservedAnalyses::none();
- }
- private:
- ScopPassT Pass;
- };
- template <typename ScopPassT>
- FunctionToScopPassAdaptor<ScopPassT>
- createFunctionToScopPassAdaptor(ScopPassT Pass) {
- return FunctionToScopPassAdaptor<ScopPassT>(std::move(Pass));
- }
- } // namespace polly
- #endif
|