diff options
Diffstat (limited to 'polly/lib')
30 files changed, 972 insertions, 2650 deletions
diff --git a/polly/lib/Analysis/DependenceInfo.cpp b/polly/lib/Analysis/DependenceInfo.cpp index c620f40..0f208ec 100644 --- a/polly/lib/Analysis/DependenceInfo.cpp +++ b/polly/lib/Analysis/DependenceInfo.cpp @@ -20,7 +20,6 @@ //===----------------------------------------------------------------------===// // #include "polly/DependenceInfo.h" -#include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "polly/ScopInfo.h" #include "polly/Support/GICHelper.h" @@ -42,6 +41,10 @@ using namespace llvm; #include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-dependence" +namespace polly { +Dependences::AnalysisLevel OptAnalysisLevel; +} + static cl::opt<int> OptComputeOut( "polly-dependences-computeout", cl::desc("Bound the dependence analysis by a maximal amount of " @@ -69,9 +72,10 @@ static cl::opt<enum AnalysisType> OptAnalysisType( "Overapproximation of dependences")), cl::Hidden, cl::init(VALUE_BASED_ANALYSIS), cl::cat(PollyCategory)); -static cl::opt<Dependences::AnalysisLevel> OptAnalysisLevel( +static cl::opt<Dependences::AnalysisLevel, true> XOptAnalysisLevel( "polly-dependences-analysis-level", cl::desc("The level of dependence analysis"), + cl::location(OptAnalysisLevel), cl::values(clEnumValN(Dependences::AL_Statement, "statement-wise", "Statement-level analysis"), clEnumValN(Dependences::AL_Reference, "reference-wise", @@ -854,240 +858,7 @@ void DependenceAnalysis::Result::abandonDependences() { Deps.release(); } -DependenceAnalysis::Result -DependenceAnalysis::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR) { - return {S, {}}; -} - -AnalysisKey DependenceAnalysis::Key; - -PreservedAnalyses -DependenceInfoPrinterPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &U) { - auto &DI = SAM.getResult<DependenceAnalysis>(S, SAR); - - if (auto d = DI.D[OptAnalysisLevel].get()) { - d->print(OS); - return PreservedAnalyses::all(); - } - - // Otherwise create the dependences on-the-fly and print them - Dependences D(S.getSharedIslCtx(), OptAnalysisLevel); - D.calculateDependences(S); - D.print(OS); - - return PreservedAnalyses::all(); -} - -const Dependences & -DependenceInfo::getDependences(Dependences::AnalysisLevel Level) { - if (Dependences *d = D[Level].get()) - return *d; - - return recomputeDependences(Level); -} - -const Dependences & -DependenceInfo::recomputeDependences(Dependences::AnalysisLevel Level) { - D[Level].reset(new Dependences(S->getSharedIslCtx(), Level)); - D[Level]->calculateDependences(*S); - return *D[Level]; -} - -void DependenceInfo::abandonDependences() { - for (std::unique_ptr<Dependences> &Deps : D) - Deps.release(); -} - -bool DependenceInfo::runOnScop(Scop &ScopVar) { - S = &ScopVar; - return false; -} - -/// Print the dependences for the given SCoP to @p OS. - -void polly::DependenceInfo::printScop(raw_ostream &OS, Scop &S) const { - if (auto d = D[OptAnalysisLevel].get()) { - d->print(OS); - return; - } - - // Otherwise create the dependences on-the-fly and print it - Dependences D(S.getSharedIslCtx(), OptAnalysisLevel); - D.calculateDependences(S); - D.print(OS); -} - -void DependenceInfo::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequiredTransitive<ScopInfoRegionPass>(); - AU.setPreservesAll(); +DependenceAnalysis::Result polly::runDependenceAnalysis(Scop &S) { + DependenceAnalysis::Result Result{S, {}}; + return Result; } - -char DependenceInfo::ID = 0; - -Pass *polly::createDependenceInfoPass() { return new DependenceInfo(); } - -INITIALIZE_PASS_BEGIN(DependenceInfo, "polly-dependences", - "Polly - Calculate dependences", false, false); -INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass); -INITIALIZE_PASS_END(DependenceInfo, "polly-dependences", - "Polly - Calculate dependences", false, false) - -//===----------------------------------------------------------------------===// - -namespace { -/// Print result from DependenceAnalysis. -class DependenceInfoPrinterLegacyPass final : public ScopPass { -public: - static char ID; - - DependenceInfoPrinterLegacyPass() : DependenceInfoPrinterLegacyPass(outs()) {} - - explicit DependenceInfoPrinterLegacyPass(llvm::raw_ostream &OS) - : ScopPass(ID), OS(OS) {} - - bool runOnScop(Scop &S) override { - DependenceInfo &P = getAnalysis<DependenceInfo>(); - - OS << "Printing analysis '" << P.getPassName() << "' for " - << "region: '" << S.getRegion().getNameStr() << "' in function '" - << S.getFunction().getName() << "':\n"; - P.printScop(OS, S); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<DependenceInfo>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char DependenceInfoPrinterLegacyPass::ID = 0; -} // namespace - -Pass *polly::createDependenceInfoPrinterLegacyPass(raw_ostream &OS) { - return new DependenceInfoPrinterLegacyPass(OS); -} - -INITIALIZE_PASS_BEGIN(DependenceInfoPrinterLegacyPass, - "polly-print-dependences", "Polly - Print dependences", - false, false); -INITIALIZE_PASS_DEPENDENCY(DependenceInfo); -INITIALIZE_PASS_END(DependenceInfoPrinterLegacyPass, "polly-print-dependences", - "Polly - Print dependences", false, false) - -//===----------------------------------------------------------------------===// - -const Dependences & -DependenceInfoWrapperPass::getDependences(Scop *S, - Dependences::AnalysisLevel Level) { - auto It = ScopToDepsMap.find(S); - if (It != ScopToDepsMap.end()) - if (It->second) { - if (It->second->getDependenceLevel() == Level) - return *It->second; - } - return recomputeDependences(S, Level); -} - -const Dependences &DependenceInfoWrapperPass::recomputeDependences( - Scop *S, Dependences::AnalysisLevel Level) { - std::unique_ptr<Dependences> D(new Dependences(S->getSharedIslCtx(), Level)); - D->calculateDependences(*S); - auto Inserted = ScopToDepsMap.insert(std::make_pair(S, std::move(D))); - return *Inserted.first->second; -} - -bool DependenceInfoWrapperPass::runOnFunction(Function &F) { - auto &SI = *getAnalysis<ScopInfoWrapperPass>().getSI(); - for (auto &It : SI) { - assert(It.second && "Invalid SCoP object!"); - recomputeDependences(It.second.get(), Dependences::AL_Access); - } - return false; -} - -void DependenceInfoWrapperPass::print(raw_ostream &OS, const Module *M) const { - for (auto &It : ScopToDepsMap) { - assert((It.first && It.second) && "Invalid Scop or Dependence object!\n"); - It.second->print(OS); - } -} - -void DependenceInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequiredTransitive<ScopInfoWrapperPass>(); - AU.setPreservesAll(); -} - -char DependenceInfoWrapperPass::ID = 0; - -Pass *polly::createDependenceInfoWrapperPassPass() { - return new DependenceInfoWrapperPass(); -} - -INITIALIZE_PASS_BEGIN( - DependenceInfoWrapperPass, "polly-function-dependences", - "Polly - Calculate dependences for all the SCoPs of a function", false, - false) -INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass); -INITIALIZE_PASS_END( - DependenceInfoWrapperPass, "polly-function-dependences", - "Polly - Calculate dependences for all the SCoPs of a function", false, - false) - -//===----------------------------------------------------------------------===// - -namespace { -/// Print result from DependenceInfoWrapperPass. -class DependenceInfoPrinterLegacyFunctionPass final : public FunctionPass { -public: - static char ID; - - DependenceInfoPrinterLegacyFunctionPass() - : DependenceInfoPrinterLegacyFunctionPass(outs()) {} - - explicit DependenceInfoPrinterLegacyFunctionPass(llvm::raw_ostream &OS) - : FunctionPass(ID), OS(OS) {} - - bool runOnFunction(Function &F) override { - DependenceInfoWrapperPass &P = getAnalysis<DependenceInfoWrapperPass>(); - - OS << "Printing analysis '" << P.getPassName() << "' for function '" - << F.getName() << "':\n"; - P.print(OS); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - FunctionPass::getAnalysisUsage(AU); - AU.addRequired<DependenceInfoWrapperPass>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char DependenceInfoPrinterLegacyFunctionPass::ID = 0; -} // namespace - -Pass *polly::createDependenceInfoPrinterLegacyFunctionPass(raw_ostream &OS) { - return new DependenceInfoPrinterLegacyFunctionPass(OS); -} - -INITIALIZE_PASS_BEGIN( - DependenceInfoPrinterLegacyFunctionPass, "polly-print-function-dependences", - "Polly - Print dependences for all the SCoPs of a function", false, false); -INITIALIZE_PASS_DEPENDENCY(DependenceInfoWrapperPass); -INITIALIZE_PASS_END(DependenceInfoPrinterLegacyFunctionPass, - "polly-print-function-dependences", - "Polly - Print dependences for all the SCoPs of a function", - false, false) diff --git a/polly/lib/Analysis/PruneUnprofitable.cpp b/polly/lib/Analysis/PruneUnprofitable.cpp index f8469c0..7201d3d1 100644 --- a/polly/lib/Analysis/PruneUnprofitable.cpp +++ b/polly/lib/Analysis/PruneUnprofitable.cpp @@ -13,7 +13,6 @@ #include "polly/PruneUnprofitable.h" #include "polly/ScopDetection.h" #include "polly/ScopInfo.h" -#include "polly/ScopPass.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Support/Debug.h" @@ -55,8 +54,9 @@ static void updateStatistics(Scop &S, bool Pruned) { NumAffineLoops += ScopStats.NumAffineLoops; } } +} // namespace -static bool runPruneUnprofitable(Scop &S) { +bool polly::runPruneUnprofitable(Scop &S) { if (PollyProcessUnprofitable) { POLLY_DEBUG( dbgs() << "NOTE: -polly-process-unprofitable active, won't prune " @@ -78,47 +78,3 @@ static bool runPruneUnprofitable(Scop &S) { return false; } - -class PruneUnprofitableWrapperPass final : public ScopPass { -public: - static char ID; - - explicit PruneUnprofitableWrapperPass() : ScopPass(ID) {} - PruneUnprofitableWrapperPass(const PruneUnprofitableWrapperPass &) = delete; - PruneUnprofitableWrapperPass & - operator=(const PruneUnprofitableWrapperPass &) = delete; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<ScopInfoRegionPass>(); - AU.setPreservesAll(); - } - - bool runOnScop(Scop &S) override { return runPruneUnprofitable(S); } -}; -} // namespace - -char PruneUnprofitableWrapperPass::ID; - -Pass *polly::createPruneUnprofitableWrapperPass() { - return new PruneUnprofitableWrapperPass(); -} - -INITIALIZE_PASS_BEGIN(PruneUnprofitableWrapperPass, "polly-prune-unprofitable", - "Polly - Prune unprofitable SCoPs", false, false) -INITIALIZE_PASS_END(PruneUnprofitableWrapperPass, "polly-prune-unprofitable", - "Polly - Prune unprofitable SCoPs", false, false) - -llvm::PreservedAnalyses -PruneUnprofitablePass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, SPMUpdater &U) { - bool Changed = runPruneUnprofitable(S); - - if (!Changed) - return PreservedAnalyses::all(); - - PreservedAnalyses PA; - PA.preserveSet<AllAnalysesOn<Module>>(); - PA.preserveSet<AllAnalysesOn<Function>>(); - PA.preserveSet<AllAnalysesOn<Loop>>(); - return PA; -} diff --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp index 67a4c43..0f96c89 100644 --- a/polly/lib/Analysis/ScopBuilder.cpp +++ b/polly/lib/Analysis/ScopBuilder.cpp @@ -56,6 +56,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include <cassert> +#include <deque> using namespace llvm; using namespace polly; @@ -1463,7 +1464,7 @@ bool ScopBuilder::buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt) { return false; SmallVector<const SCEV *, 4> Subscripts; - SmallVector<int, 4> Sizes; + SmallVector<const SCEV *, 4> Sizes; getIndexExpressionsFromGEP(SE, GEP, Subscripts, Sizes); auto *BasePtr = GEP->getOperand(0); @@ -1475,8 +1476,6 @@ bool ScopBuilder::buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt) { if (BasePtr != BasePointer->getValue()) return false; - std::vector<const SCEV *> SizesSCEV; - const InvariantLoadsSetTy &ScopRIL = scop->getRequiredInvariantLoads(); Loop *SurroundingLoop = Stmt->getSurroundingLoop(); @@ -1494,11 +1493,9 @@ bool ScopBuilder::buildAccessMultiDimFixed(MemAccInst Inst, ScopStmt *Stmt) { if (Sizes.empty()) return false; + std::vector<const SCEV *> SizesSCEV; SizesSCEV.push_back(nullptr); - - for (auto V : Sizes) - SizesSCEV.push_back(SE.getSCEV( - ConstantInt::get(IntegerType::getInt64Ty(BasePtr->getContext()), V))); + SizesSCEV.insert(SizesSCEV.end(), Sizes.begin(), Sizes.end()); addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType, true, Subscripts, SizesSCEV, Val); diff --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp index 43ed863..9e0b495 100644 --- a/polly/lib/Analysis/ScopDetection.cpp +++ b/polly/lib/Analysis/ScopDetection.cpp @@ -44,7 +44,6 @@ //===----------------------------------------------------------------------===// #include "polly/ScopDetection.h" -#include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "polly/ScopDetectionDiagnostic.h" #include "polly/Support/SCEVValidator.h" @@ -73,10 +72,7 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" -#include "llvm/IR/PassManager.h" #include "llvm/IR/Value.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Regex.h" #include "llvm/Support/raw_ostream.h" @@ -1983,53 +1979,12 @@ void ScopDetection::verifyAnalysis() { verifyRegion(*R); } -bool ScopDetectionWrapperPass::runOnFunction(Function &F) { - auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); - auto &RI = getAnalysis<RegionInfoPass>().getRegionInfo(); - auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults(); - auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); - auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); - - Result = std::make_unique<ScopDetection>(DT, SE, LI, RI, AA, ORE); - Result->detect(F); - return false; -} - -void ScopDetectionWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<LoopInfoWrapperPass>(); - AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); - AU.addRequired<DominatorTreeWrapperPass>(); - AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); - // We also need AA and RegionInfo when we are verifying analysis. - AU.addRequiredTransitive<AAResultsWrapperPass>(); - AU.addRequiredTransitive<RegionInfoPass>(); - AU.setPreservesAll(); -} - -void ScopDetectionWrapperPass::print(raw_ostream &OS, const Module *) const { - for (const Region *R : Result->ValidRegions) - OS << "Valid Region for Scop: " << R->getNameStr() << '\n'; - - OS << "\n"; -} - -ScopDetectionWrapperPass::ScopDetectionWrapperPass() : FunctionPass(ID) { - // Disable runtime alias checks if we ignore aliasing all together. - if (IgnoreAliasing) - PollyUseRuntimeAliasChecks = false; -} - ScopAnalysis::ScopAnalysis() { // Disable runtime alias checks if we ignore aliasing all together. if (IgnoreAliasing) PollyUseRuntimeAliasChecks = false; } -void ScopDetectionWrapperPass::releaseMemory() { Result.reset(); } - -char ScopDetectionWrapperPass::ID; - AnalysisKey ScopAnalysis::Key; ScopDetection ScopAnalysis::run(Function &F, FunctionAnalysisManager &FAM) { @@ -2055,66 +2010,3 @@ PreservedAnalyses ScopAnalysisPrinterPass::run(Function &F, OS << "\n"; return PreservedAnalyses::all(); } - -Pass *polly::createScopDetectionWrapperPassPass() { - return new ScopDetectionWrapperPass(); -} - -INITIALIZE_PASS_BEGIN(ScopDetectionWrapperPass, "polly-detect", - "Polly - Detect static control parts (SCoPs)", false, - false); -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass); -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); -INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); -INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); -INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass); -INITIALIZE_PASS_END(ScopDetectionWrapperPass, "polly-detect", - "Polly - Detect static control parts (SCoPs)", false, false) - -//===----------------------------------------------------------------------===// - -namespace { -/// Print result from ScopDetectionWrapperPass. -class ScopDetectionPrinterLegacyPass final : public FunctionPass { -public: - static char ID; - - ScopDetectionPrinterLegacyPass() : ScopDetectionPrinterLegacyPass(outs()) {} - - explicit ScopDetectionPrinterLegacyPass(llvm::raw_ostream &OS) - : FunctionPass(ID), OS(OS) {} - - bool runOnFunction(Function &F) override { - ScopDetectionWrapperPass &P = getAnalysis<ScopDetectionWrapperPass>(); - - OS << "Printing analysis '" << P.getPassName() << "' for function '" - << F.getName() << "':\n"; - P.print(OS); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - FunctionPass::getAnalysisUsage(AU); - AU.addRequired<ScopDetectionWrapperPass>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char ScopDetectionPrinterLegacyPass::ID = 0; -} // namespace - -Pass *polly::createScopDetectionPrinterLegacyPass(raw_ostream &OS) { - return new ScopDetectionPrinterLegacyPass(OS); -} - -INITIALIZE_PASS_BEGIN(ScopDetectionPrinterLegacyPass, "polly-print-detect", - "Polly - Print static control parts (SCoPs)", false, - false); -INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass); -INITIALIZE_PASS_END(ScopDetectionPrinterLegacyPass, "polly-print-detect", - "Polly - Print static control parts (SCoPs)", false, false) diff --git a/polly/lib/Analysis/ScopGraphPrinter.cpp b/polly/lib/Analysis/ScopGraphPrinter.cpp index eb6c995..29e2128 100644 --- a/polly/lib/Analysis/ScopGraphPrinter.cpp +++ b/polly/lib/Analysis/ScopGraphPrinter.cpp @@ -14,20 +14,26 @@ //===----------------------------------------------------------------------===// #include "polly/ScopGraphPrinter.h" -#include "polly/LinkAllPasses.h" #include "polly/ScopDetection.h" #include "llvm/Support/CommandLine.h" using namespace polly; using namespace llvm; -static cl::opt<std::string> - ViewFilter("polly-view-only", - cl::desc("Only view functions that match this pattern"), - cl::Hidden, cl::init("")); -static cl::opt<bool> ViewAll("polly-view-all", - cl::desc("Also show functions without any scops"), - cl::Hidden, cl::init(false)); +namespace polly { +std::string ViewFilter; +bool ViewAll; +} // namespace polly + +static cl::opt<std::string, true> + XViewFilter("polly-view-only", + cl::desc("Only view functions that match this pattern"), + cl::location(ViewFilter), cl::Hidden, cl::init("")); + +static cl::opt<bool, true> + XViewAll("polly-view-all", + cl::desc("Also show functions without any scops"), + cl::location(ViewAll), cl::Hidden, cl::init(false)); namespace llvm { @@ -134,104 +140,6 @@ void DOTGraphTraits<ScopDetection *>::addCustomGraphFeatures( } // namespace llvm -struct ScopDetectionAnalysisGraphTraits { - static ScopDetection *getGraph(ScopDetectionWrapperPass *Analysis) { - return &Analysis->getSD(); - } -}; - -struct ScopViewerWrapperPass - : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false, - ScopDetection *, - ScopDetectionAnalysisGraphTraits> { - static char ID; - ScopViewerWrapperPass() - : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false, - ScopDetection *, - ScopDetectionAnalysisGraphTraits>( - "scops", ID) {} - bool processFunction(Function &F, ScopDetectionWrapperPass &SD) override { - if (ViewFilter != "" && !F.getName().count(ViewFilter)) - return false; - - if (ViewAll) - return true; - - // Check that at least one scop was detected. - return std::distance(SD.getSD().begin(), SD.getSD().end()) > 0; - } -}; -char ScopViewerWrapperPass::ID = 0; - -struct ScopOnlyViewerWrapperPass - : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false, - ScopDetection *, - ScopDetectionAnalysisGraphTraits> { - static char ID; - ScopOnlyViewerWrapperPass() - : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false, - ScopDetection *, - ScopDetectionAnalysisGraphTraits>( - "scopsonly", ID) {} -}; -char ScopOnlyViewerWrapperPass::ID = 0; - -struct ScopPrinterWrapperPass - : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false, - ScopDetection *, - ScopDetectionAnalysisGraphTraits> { - static char ID; - ScopPrinterWrapperPass() - : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false, - ScopDetection *, - ScopDetectionAnalysisGraphTraits>( - "scops", ID) {} -}; -char ScopPrinterWrapperPass::ID = 0; - -struct ScopOnlyPrinterWrapperPass - : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true, - ScopDetection *, - ScopDetectionAnalysisGraphTraits> { - static char ID; - ScopOnlyPrinterWrapperPass() - : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true, - ScopDetection *, - ScopDetectionAnalysisGraphTraits>( - "scopsonly", ID) {} -}; -char ScopOnlyPrinterWrapperPass::ID = 0; - -static RegisterPass<ScopViewerWrapperPass> X("view-scops", - "Polly - View Scops of function"); - -static RegisterPass<ScopOnlyViewerWrapperPass> - Y("view-scops-only", - "Polly - View Scops of function (with no function bodies)"); - -static RegisterPass<ScopPrinterWrapperPass> - M("dot-scops", "Polly - Print Scops of function"); - -static RegisterPass<ScopOnlyPrinterWrapperPass> - N("dot-scops-only", - "Polly - Print Scops of function (with no function bodies)"); - -Pass *polly::createDOTViewerWrapperPass() { - return new ScopViewerWrapperPass(); -} - -Pass *polly::createDOTOnlyViewerWrapperPass() { - return new ScopOnlyViewerWrapperPass(); -} - -Pass *polly::createDOTPrinterWrapperPass() { - return new ScopPrinterWrapperPass(); -} - -Pass *polly::createDOTOnlyPrinterWrapperPass() { - return new ScopOnlyPrinterWrapperPass(); -} - bool ScopViewer::processFunction(Function &F, const ScopDetection &SD) { if (ViewFilter != "" && !F.getName().count(ViewFilter)) return false; diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp index 8c6a236..bf993a2 100644 --- a/polly/lib/Analysis/ScopInfo.cpp +++ b/polly/lib/Analysis/ScopInfo.cpp @@ -17,7 +17,6 @@ //===----------------------------------------------------------------------===// #include "polly/ScopInfo.h" -#include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "polly/ScopBuilder.h" #include "polly/ScopDetection.h" @@ -54,10 +53,8 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" -#include "llvm/IR/PassManager.h" #include "llvm/IR/Type.h" #include "llvm/IR/Value.h" -#include "llvm/InitializePasses.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -2544,19 +2541,6 @@ raw_ostream &polly::operator<<(raw_ostream &OS, const Scop &scop) { return OS; } -//===----------------------------------------------------------------------===// -void ScopInfoRegionPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<LoopInfoWrapperPass>(); - AU.addRequired<RegionInfoPass>(); - AU.addRequired<DominatorTreeWrapperPass>(); - AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); - AU.addRequiredTransitive<ScopDetectionWrapperPass>(); - AU.addRequired<AAResultsWrapperPass>(); - AU.addRequired<AssumptionCacheTracker>(); - AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); - AU.setPreservesAll(); -} - void updateLoopCountStatistic(ScopDetection::LoopStats Stats, Scop::ScopStatistics ScopStats) { assert(Stats.NumLoops == ScopStats.NumAffineLoops + ScopStats.NumBoxedLoops); @@ -2592,112 +2576,6 @@ void updateLoopCountStatistic(ScopDetection::LoopStats Stats, NumSingletonWritesInLoops += ScopStats.NumSingletonWritesInLoops; } -bool ScopInfoRegionPass::runOnRegion(Region *R, RGPassManager &RGM) { - auto &SD = getAnalysis<ScopDetectionWrapperPass>().getSD(); - - if (!SD.isMaxRegionInScop(*R)) - return false; - - Function *F = R->getEntry()->getParent(); - auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); - auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); - auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults(); - auto const &DL = F->getParent()->getDataLayout(); - auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(*F); - auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); - - ScopBuilder SB(R, AC, AA, DL, DT, LI, SD, SE, ORE); - S = SB.getScop(); // take ownership of scop object - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) - if (S) { - ScopDetection::LoopStats Stats = - ScopDetection::countBeneficialLoops(&S->getRegion(), SE, LI, 0); - updateLoopCountStatistic(Stats, S->getStatistics()); - } -#endif - - return false; -} - -void ScopInfoRegionPass::print(raw_ostream &OS, const Module *) const { - if (S) - S->print(OS, PollyPrintInstructions); - else - OS << "Invalid Scop!\n"; -} - -char ScopInfoRegionPass::ID = 0; - -Pass *polly::createScopInfoRegionPassPass() { return new ScopInfoRegionPass(); } - -INITIALIZE_PASS_BEGIN(ScopInfoRegionPass, "polly-scops", - "Polly - Create polyhedral description of Scops", false, - false); -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass); -INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker); -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); -INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); -INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); -INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass); -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); -INITIALIZE_PASS_END(ScopInfoRegionPass, "polly-scops", - "Polly - Create polyhedral description of Scops", false, - false) - -//===----------------------------------------------------------------------===// - -namespace { - -/// Print result from ScopInfoRegionPass. -class ScopInfoPrinterLegacyRegionPass final : public RegionPass { -public: - static char ID; - - ScopInfoPrinterLegacyRegionPass() : ScopInfoPrinterLegacyRegionPass(outs()) {} - - explicit ScopInfoPrinterLegacyRegionPass(llvm::raw_ostream &OS) - : RegionPass(ID), OS(OS) {} - - bool runOnRegion(Region *R, RGPassManager &RGM) override { - ScopInfoRegionPass &P = getAnalysis<ScopInfoRegionPass>(); - - OS << "Printing analysis '" << P.getPassName() << "' for region: '" - << R->getNameStr() << "' in function '" - << R->getEntry()->getParent()->getName() << "':\n"; - P.print(OS); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - RegionPass::getAnalysisUsage(AU); - AU.addRequired<ScopInfoRegionPass>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char ScopInfoPrinterLegacyRegionPass::ID = 0; -} // namespace - -Pass *polly::createScopInfoPrinterLegacyRegionPass(raw_ostream &OS) { - return new ScopInfoPrinterLegacyRegionPass(OS); -} - -INITIALIZE_PASS_BEGIN(ScopInfoPrinterLegacyRegionPass, "polly-print-scops", - "Polly - Print polyhedral description of Scops", false, - false); -INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass); -INITIALIZE_PASS_END(ScopInfoPrinterLegacyRegionPass, "polly-print-scops", - "Polly - Print polyhedral description of Scops", false, - false) - -//===----------------------------------------------------------------------===// - ScopInfo::ScopInfo(const DataLayout &DL, ScopDetection &SD, ScalarEvolution &SE, LoopInfo &LI, AliasAnalysis &AA, DominatorTree &DT, AssumptionCache &AC, OptimizationRemarkEmitter &ORE) @@ -2771,110 +2649,3 @@ PreservedAnalyses ScopInfoPrinterPass::run(Function &F, } return PreservedAnalyses::all(); } - -void ScopInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<LoopInfoWrapperPass>(); - AU.addRequired<RegionInfoPass>(); - AU.addRequired<DominatorTreeWrapperPass>(); - AU.addRequiredTransitive<ScalarEvolutionWrapperPass>(); - AU.addRequiredTransitive<ScopDetectionWrapperPass>(); - AU.addRequired<AAResultsWrapperPass>(); - AU.addRequired<AssumptionCacheTracker>(); - AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); - AU.setPreservesAll(); -} - -bool ScopInfoWrapperPass::runOnFunction(Function &F) { - auto &SD = getAnalysis<ScopDetectionWrapperPass>().getSD(); - auto &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); - auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); - auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults(); - auto const &DL = F.getParent()->getDataLayout(); - auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - auto &AC = getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); - auto &ORE = getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); - - Result.reset(new ScopInfo{DL, SD, SE, LI, AA, DT, AC, ORE}); - return false; -} - -void ScopInfoWrapperPass::print(raw_ostream &OS, const Module *) const { - for (auto &It : *Result) { - if (It.second) - It.second->print(OS, PollyPrintInstructions); - else - OS << "Invalid Scop!\n"; - } -} - -char ScopInfoWrapperPass::ID = 0; - -Pass *polly::createScopInfoWrapperPassPass() { - return new ScopInfoWrapperPass(); -} - -INITIALIZE_PASS_BEGIN( - ScopInfoWrapperPass, "polly-function-scops", - "Polly - Create polyhedral description of all Scops of a function", false, - false); -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass); -INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker); -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); -INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); -INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); -INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass); -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); -INITIALIZE_PASS_END( - ScopInfoWrapperPass, "polly-function-scops", - "Polly - Create polyhedral description of all Scops of a function", false, - false) - -//===----------------------------------------------------------------------===// - -namespace { -/// Print result from ScopInfoWrapperPass. -class ScopInfoPrinterLegacyFunctionPass final : public FunctionPass { -public: - static char ID; - - ScopInfoPrinterLegacyFunctionPass() - : ScopInfoPrinterLegacyFunctionPass(outs()) {} - explicit ScopInfoPrinterLegacyFunctionPass(llvm::raw_ostream &OS) - : FunctionPass(ID), OS(OS) {} - - bool runOnFunction(Function &F) override { - ScopInfoWrapperPass &P = getAnalysis<ScopInfoWrapperPass>(); - - OS << "Printing analysis '" << P.getPassName() << "' for function '" - << F.getName() << "':\n"; - P.print(OS); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - FunctionPass::getAnalysisUsage(AU); - AU.addRequired<ScopInfoWrapperPass>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char ScopInfoPrinterLegacyFunctionPass::ID = 0; -} // namespace - -Pass *polly::createScopInfoPrinterLegacyFunctionPass(raw_ostream &OS) { - return new ScopInfoPrinterLegacyFunctionPass(OS); -} - -INITIALIZE_PASS_BEGIN( - ScopInfoPrinterLegacyFunctionPass, "polly-print-function-scops", - "Polly - Print polyhedral description of all Scops of a function", false, - false); -INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass); -INITIALIZE_PASS_END( - ScopInfoPrinterLegacyFunctionPass, "polly-print-function-scops", - "Polly - Print polyhedral description of all Scops of a function", false, - false) diff --git a/polly/lib/Analysis/ScopPass.cpp b/polly/lib/Analysis/ScopPass.cpp deleted file mode 100644 index 719cd0f..0000000 --- a/polly/lib/Analysis/ScopPass.cpp +++ /dev/null @@ -1,170 +0,0 @@ -//===- ScopPass.cpp - The base class of Passes that operate on Polly IR ---===// -// -// 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 contains the definitions of the ScopPass members. -// -//===----------------------------------------------------------------------===// - -#include "polly/ScopPass.h" -#include "polly/ScopInfo.h" -#include "llvm/Analysis/BasicAliasAnalysis.h" -#include "llvm/Analysis/GlobalsModRef.h" -#include "llvm/Analysis/LazyBlockFrequencyInfo.h" -#include "llvm/Analysis/LazyBranchProbabilityInfo.h" -#include "llvm/Analysis/OptimizationRemarkEmitter.h" -#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include <optional> - -using namespace llvm; -using namespace polly; - -bool ScopPass::runOnRegion(Region *R, RGPassManager &RGM) { - S = nullptr; - - if (skipRegion(*R)) - return false; - - if ((S = getAnalysis<ScopInfoRegionPass>().getScop())) - return runOnScop(*S); - - return false; -} - -void ScopPass::print(raw_ostream &OS, const Module *M) const { - if (S) - printScop(OS, *S); -} - -void ScopPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<ScopInfoRegionPass>(); - - AU.addPreserved<AAResultsWrapperPass>(); - AU.addPreserved<BasicAAWrapperPass>(); - AU.addPreserved<LoopInfoWrapperPass>(); - AU.addPreserved<DominatorTreeWrapperPass>(); - AU.addPreserved<GlobalsAAWrapperPass>(); - AU.addPreserved<ScopDetectionWrapperPass>(); - AU.addPreserved<ScalarEvolutionWrapperPass>(); - AU.addPreserved<SCEVAAWrapperPass>(); - AU.addPreserved<OptimizationRemarkEmitterWrapperPass>(); - AU.addPreserved<LazyBlockFrequencyInfoPass>(); - AU.addPreserved<LazyBranchProbabilityInfoPass>(); - AU.addPreserved<RegionInfoPass>(); - AU.addPreserved<ScopInfoRegionPass>(); - AU.addPreserved<TargetTransformInfoWrapperPass>(); -} - -namespace polly { -template class OwningInnerAnalysisManagerProxy<ScopAnalysisManager, Function>; -} - -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<ScopInfoAnalysis>(F, PA) || - Inv.invalidate<ScalarEvolutionAnalysis>(F, PA) || - Inv.invalidate<LoopAnalysis>(F, PA) || - Inv.invalidate<DominatorTreeAnalysis>(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, scop->getName()); - - 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) { - std::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 - -namespace polly { -template <> -OwningScopAnalysisManagerFunctionProxy::Result -OwningScopAnalysisManagerFunctionProxy::run(Function &F, - FunctionAnalysisManager &FAM) { - return Result(InnerAM, FAM.getResult<ScopInfoAnalysis>(F)); -} -} // namespace polly diff --git a/polly/lib/CMakeLists.txt b/polly/lib/CMakeLists.txt index 0ed6738..7c609fd 100644 --- a/polly/lib/CMakeLists.txt +++ b/polly/lib/CMakeLists.txt @@ -48,7 +48,6 @@ add_llvm_pass_plugin(Polly Analysis/ScopInfo.cpp Analysis/ScopBuilder.cpp Analysis/ScopGraphPrinter.cpp - Analysis/ScopPass.cpp Analysis/PruneUnprofitable.cpp CodeGen/BlockGenerators.cpp ${ISL_CODEGEN_FILES} @@ -60,6 +59,9 @@ add_llvm_pass_plugin(Polly CodeGen/RuntimeDebugBuilder.cpp CodeGen/PerfMonitor.cpp Exchange/JSONExporter.cpp + Pass/PhaseManager.cpp + Pass/PollyFunctionPass.cpp + Pass/PollyModulePass.cpp Support/GICHelper.cpp Support/PollyDebug.cpp Support/SCEVAffinator.cpp diff --git a/polly/lib/CodeGen/CodeGeneration.cpp b/polly/lib/CodeGen/CodeGeneration.cpp index 2d8b393..5d2b6363 100644 --- a/polly/lib/CodeGen/CodeGeneration.cpp +++ b/polly/lib/CodeGen/CodeGeneration.cpp @@ -25,7 +25,6 @@ #include "polly/CodeGen/PerfMonitor.h" #include "polly/CodeGen/Utils.h" #include "polly/DependenceInfo.h" -#include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "polly/ScopInfo.h" #include "polly/Support/ScopHelper.h" @@ -35,9 +34,7 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" -#include "llvm/IR/PassManager.h" #include "llvm/IR/Verifier.h" -#include "llvm/InitializePasses.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -235,15 +232,6 @@ static bool generateCode(Scop &S, IslAstInfo &AI, LoopInfo &LI, NodeBuilder.allocateNewArrays(StartExitBlocks); Annotator.buildAliasScopes(S); - // The code below annotates the "llvm.loop.vectorize.enable" to false - // for the code flow taken when RTCs fail. Because we don't want the - // Loop Vectorizer to come in later and vectorize the original fall back - // loop when Polly is enabled. - for (Loop *L : LI.getLoopsInPreorder()) { - if (S.contains(L)) - addStringMetadataToLoop(L, "llvm.loop.vectorize.enable", 0); - } - if (PerfMonitoring) { PerfMonitor P(S, EnteringBB->getParent()->getParent()); P.initialize(); @@ -285,6 +273,21 @@ static bool generateCode(Scop &S, IslAstInfo &AI, LoopInfo &LI, Builder.GetInsertBlock()->getTerminator()->setOperand(0, RTC); + auto *CI = dyn_cast<ConstantInt>(RTC); + // The code below annotates the "llvm.loop.vectorize.enable" to false + // for the code flow taken when RTCs fail. Because we don't want the + // Loop Vectorizer to come in later and vectorize the original fall back + // loop when Polly is enabled. This avoids loop versioning on fallback + // loop by Loop Vectorizer. Don't do this when Polly's RTC value is + // false (due to code generation failure), as we are left with only one + // version of Loop. + if (!(CI && CI->isZero())) { + for (Loop *L : LI.getLoopsInPreorder()) { + if (S.contains(L)) + addStringMetadataToLoop(L, "llvm.loop.vectorize.enable", 0); + } + } + // Explicitly set the insert point to the end of the block to avoid that a // split at the builder's current // insert position would move the malloc calls to the wrong BasicBlock. @@ -314,82 +317,6 @@ static bool generateCode(Scop &S, IslAstInfo &AI, LoopInfo &LI, return true; } -namespace { - -class CodeGeneration final : public ScopPass { -public: - static char ID; - - /// The data layout used. - const DataLayout *DL; - - /// @name The analysis passes we need to generate code. - /// - ///{ - LoopInfo *LI; - IslAstInfo *AI; - DominatorTree *DT; - ScalarEvolution *SE; - RegionInfo *RI; - ///} - - CodeGeneration() : ScopPass(ID) {} - - /// Generate LLVM-IR for the SCoP @p S. - bool runOnScop(Scop &S) override { - AI = &getAnalysis<IslAstInfoWrapperPass>().getAI(); - LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); - DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); - DL = &S.getFunction().getDataLayout(); - RI = &getAnalysis<RegionInfoPass>().getRegionInfo(); - return generateCode(S, *AI, *LI, *DT, *SE, *RI); - } - - /// Register all analyses and transformation required. - void getAnalysisUsage(AnalysisUsage &AU) const override { - ScopPass::getAnalysisUsage(AU); - - AU.addRequired<DominatorTreeWrapperPass>(); - AU.addRequired<IslAstInfoWrapperPass>(); - AU.addRequired<RegionInfoPass>(); - AU.addRequired<ScalarEvolutionWrapperPass>(); - AU.addRequired<ScopDetectionWrapperPass>(); - AU.addRequired<ScopInfoRegionPass>(); - AU.addRequired<LoopInfoWrapperPass>(); - - AU.addPreserved<DependenceInfo>(); - AU.addPreserved<IslAstInfoWrapperPass>(); - - // FIXME: We do not yet add regions for the newly generated code to the - // region tree. - } -}; -} // namespace - -PreservedAnalyses CodeGenerationPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &AR, - SPMUpdater &U) { - auto &AI = SAM.getResult<IslAstAnalysis>(S, AR); - if (generateCode(S, AI, AR.LI, AR.DT, AR.SE, AR.RI)) { - U.invalidateScop(S); - return PreservedAnalyses::none(); - } - - return PreservedAnalyses::all(); +bool polly::runCodeGeneration(Scop &S, RegionInfo &RI, IslAstInfo &AI) { + return generateCode(S, AI, *S.getLI(), *S.getDT(), *S.getSE(), RI); } - -char CodeGeneration::ID = 1; - -Pass *polly::createCodeGenerationPass() { return new CodeGeneration(); } - -INITIALIZE_PASS_BEGIN(CodeGeneration, "polly-codegen", - "Polly - Create LLVM-IR from SCoPs", false, false); -INITIALIZE_PASS_DEPENDENCY(DependenceInfo); -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass); -INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); -INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); -INITIALIZE_PASS_DEPENDENCY(ScopDetectionWrapperPass); -INITIALIZE_PASS_END(CodeGeneration, "polly-codegen", - "Polly - Create LLVM-IR from SCoPs", false, false) diff --git a/polly/lib/CodeGen/IslAst.cpp b/polly/lib/CodeGen/IslAst.cpp index 09bacda..0ea14ae 100644 --- a/polly/lib/CodeGen/IslAst.cpp +++ b/polly/lib/CodeGen/IslAst.cpp @@ -29,11 +29,9 @@ #include "polly/CodeGen/IslAst.h" #include "polly/CodeGen/CodeGeneration.h" #include "polly/DependenceInfo.h" -#include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "polly/ScopDetection.h" #include "polly/ScopInfo.h" -#include "polly/ScopPass.h" #include "polly/Support/GICHelper.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/Function.h" @@ -83,6 +81,11 @@ static cl::opt<bool> DetectParallel("polly-ast-detect-parallel", cl::desc("Detect parallelism"), cl::Hidden, cl::cat(PollyCategory)); +static cl::opt<bool> + PollyPrintAst("polly-print-ast", + cl::desc("Print the ISL abstract syntax tree"), + cl::cat(PollyCategory)); + STATISTIC(ScopsProcessed, "Number of SCoPs processed"); STATISTIC(ScopsBeneficial, "Number of beneficial SCoPs"); STATISTIC(BeneficialAffineLoops, "Number of beneficial affine loops"); @@ -659,15 +662,6 @@ static std::unique_ptr<IslAstInfo> runIslAst( return Ast; } -IslAstInfo IslAstAnalysis::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR) { - auto GetDeps = [&](Dependences::AnalysisLevel Lvl) -> const Dependences & { - return SAM.getResult<DependenceAnalysis>(S, SAR).getDependences(Lvl); - }; - - return std::move(*runIslAst(S, GetDeps)); -} - static __isl_give isl_printer *cbPrintUser(__isl_take isl_printer *P, __isl_take isl_ast_print_options *O, __isl_keep isl_ast_node *Node, @@ -767,99 +761,19 @@ void IslAstInfo::print(raw_ostream &OS) { isl_printer_free(P); } -AnalysisKey IslAstAnalysis::Key; -PreservedAnalyses IslAstPrinterPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &U) { - auto &Ast = SAM.getResult<IslAstAnalysis>(S, SAR); - Ast.print(OS); - return PreservedAnalyses::all(); -} - -void IslAstInfoWrapperPass::releaseMemory() { Ast.reset(); } - -bool IslAstInfoWrapperPass::runOnScop(Scop &Scop) { - auto GetDeps = [this](Dependences::AnalysisLevel Lvl) -> const Dependences & { - return getAnalysis<DependenceInfo>().getDependences(Lvl); +std::unique_ptr<IslAstInfo> +polly::runIslAstGen(Scop &S, DependenceAnalysis::Result &DA) { + auto GetDeps = [&](Dependences::AnalysisLevel Lvl) -> const Dependences & { + return DA.getDependences(Lvl); }; - Ast = runIslAst(Scop, GetDeps); - - return false; -} - -void IslAstInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { - // Get the Common analysis usage of ScopPasses. - ScopPass::getAnalysisUsage(AU); - AU.addRequiredTransitive<ScopInfoRegionPass>(); - AU.addRequired<DependenceInfo>(); - - AU.addPreserved<DependenceInfo>(); -} - -void IslAstInfoWrapperPass::printScop(raw_ostream &OS, Scop &S) const { - OS << "Printing analysis 'Polly - Generate an AST of the SCoP (isl)'" - << S.getName() << "' in function '" << S.getFunction().getName() << "':\n"; - if (Ast) - Ast->print(OS); -} - -char IslAstInfoWrapperPass::ID = 0; - -Pass *polly::createIslAstInfoWrapperPassPass() { - return new IslAstInfoWrapperPass(); -} - -INITIALIZE_PASS_BEGIN(IslAstInfoWrapperPass, "polly-ast", - "Polly - Generate an AST of the SCoP (isl)", false, - false); -INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass); -INITIALIZE_PASS_DEPENDENCY(DependenceInfo); -INITIALIZE_PASS_END(IslAstInfoWrapperPass, "polly-ast", - "Polly - Generate an AST from the SCoP (isl)", false, false) - -//===----------------------------------------------------------------------===// - -namespace { -/// Print result from IslAstInfoWrapperPass. -class IslAstInfoPrinterLegacyPass final : public ScopPass { -public: - static char ID; - - IslAstInfoPrinterLegacyPass() : IslAstInfoPrinterLegacyPass(outs()) {} - explicit IslAstInfoPrinterLegacyPass(llvm::raw_ostream &OS) - : ScopPass(ID), OS(OS) {} - - bool runOnScop(Scop &S) override { - IslAstInfoWrapperPass &P = getAnalysis<IslAstInfoWrapperPass>(); - - OS << "Printing analysis '" << P.getPassName() << "' for region: '" - << S.getRegion().getNameStr() << "' in function '" - << S.getFunction().getName() << "':\n"; - P.printScop(OS, S); - - return false; + std::unique_ptr<IslAstInfo> Result = runIslAst(S, GetDeps); + if (PollyPrintAst) { + outs() << "Printing analysis 'Polly - Generate an AST of the SCoP (isl)'" + << S.getName() << "' in function '" << S.getFunction().getName() + << "':\n"; + if (Result) + Result->print(llvm::outs()); } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<IslAstInfoWrapperPass>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char IslAstInfoPrinterLegacyPass::ID = 0; -} // namespace - -Pass *polly::createIslAstInfoPrinterLegacyPass(raw_ostream &OS) { - return new IslAstInfoPrinterLegacyPass(OS); + return Result; } - -INITIALIZE_PASS_BEGIN(IslAstInfoPrinterLegacyPass, "polly-print-ast", - "Polly - Print the AST from a SCoP (isl)", false, false); -INITIALIZE_PASS_DEPENDENCY(IslAstInfoWrapperPass); -INITIALIZE_PASS_END(IslAstInfoPrinterLegacyPass, "polly-print-ast", - "Polly - Print the AST from a SCoP (isl)", false, false) diff --git a/polly/lib/Exchange/JSONExporter.cpp b/polly/lib/Exchange/JSONExporter.cpp index dfd6314..e392066 100644 --- a/polly/lib/Exchange/JSONExporter.cpp +++ b/polly/lib/Exchange/JSONExporter.cpp @@ -12,10 +12,8 @@ #include "polly/JSONExporter.h" #include "polly/DependenceInfo.h" -#include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "polly/ScopInfo.h" -#include "polly/ScopPass.h" #include "polly/Support/ISLTools.h" #include "polly/Support/ScopLocation.h" #include "llvm/ADT/Statistic.h" @@ -36,6 +34,11 @@ using namespace polly; #define DEBUG_TYPE "polly-import-jscop" +static cl::opt<bool> + PollyPrintImportJscop("polly-print-import-jscop", + cl::desc("Polly - Print Scop import result"), + cl::cat(PollyCategory)); + STATISTIC(NewAccessMapFound, "Number of updated access functions"); namespace { @@ -50,36 +53,6 @@ static cl::opt<std::string> cl::desc("Postfix to append to the import .jsop files."), cl::Hidden, cl::value_desc("File postfix"), cl::ValueRequired, cl::init(""), cl::cat(PollyCategory)); - -class JSONExporter : public ScopPass { -public: - static char ID; - explicit JSONExporter() : ScopPass(ID) {} - - /// Export the SCoP @p S to a JSON file. - bool runOnScop(Scop &S) override; - - /// Print the SCoP @p S as it is exported. - void printScop(raw_ostream &OS, Scop &S) const override; - - /// Register all analyses and transformation required. - void getAnalysisUsage(AnalysisUsage &AU) const override; -}; - -class JSONImporter : public ScopPass { -public: - static char ID; - std::vector<std::string> NewAccessStrings; - explicit JSONImporter() : ScopPass(ID) {} - /// Import new access functions for SCoP @p S from a JSON file. - bool runOnScop(Scop &S) override; - - /// Print the SCoP @p S and the imported access functions. - void printScop(raw_ostream &OS, Scop &S) const override; - - /// Register all analyses and transformation required. - void getAnalysisUsage(AnalysisUsage &AU) const override; -}; } // namespace static std::string getFileName(Scop &S, StringRef Suffix = "") { @@ -742,140 +715,24 @@ static bool importScop(Scop &S, const Dependences &D, const DataLayout &DL, return true; } -char JSONExporter::ID = 0; -void JSONExporter::printScop(raw_ostream &OS, Scop &S) const { OS << S; } - -bool JSONExporter::runOnScop(Scop &S) { - exportScop(S); - return false; -} - -void JSONExporter::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesAll(); - AU.addRequired<ScopInfoRegionPass>(); -} - -Pass *polly::createJSONExporterPass() { return new JSONExporter(); } - -PreservedAnalyses JSONExportPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &) { - exportScop(S); - return PreservedAnalyses::all(); -} - -char JSONImporter::ID = 0; - -void JSONImporter::printScop(raw_ostream &OS, Scop &S) const { - OS << S; - for (std::vector<std::string>::const_iterator I = NewAccessStrings.begin(), - E = NewAccessStrings.end(); - I != E; I++) - OS << "New access function '" << *I << "' detected in JSCOP file\n"; -} - -bool JSONImporter::runOnScop(Scop &S) { - const Dependences &D = - getAnalysis<DependenceInfo>().getDependences(Dependences::AL_Statement); +void polly::runImportJSON(Scop &S, DependenceAnalysis::Result &DA) { + const Dependences &D = DA.getDependences(Dependences::AL_Statement); const DataLayout &DL = S.getFunction().getParent()->getDataLayout(); - + std::vector<std::string> NewAccessStrings; if (!importScop(S, D, DL, &NewAccessStrings)) report_fatal_error("Tried to import a malformed jscop file."); - return false; -} - -void JSONImporter::getAnalysisUsage(AnalysisUsage &AU) const { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<DependenceInfo>(); - - // TODO: JSONImporter should throw away DependenceInfo. - AU.addPreserved<DependenceInfo>(); -} - -Pass *polly::createJSONImporterPass() { return new JSONImporter(); } - -PreservedAnalyses JSONImportPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &) { - const Dependences &D = - SAM.getResult<DependenceAnalysis>(S, SAR).getDependences( - Dependences::AL_Statement); - const DataLayout &DL = S.getFunction().getParent()->getDataLayout(); - - if (!importScop(S, D, DL)) - report_fatal_error("Tried to import a malformed jscop file."); - - // This invalidates all analyses on Scop. - PreservedAnalyses PA; - PA.preserveSet<AllAnalysesOn<Module>>(); - PA.preserveSet<AllAnalysesOn<Function>>(); - PA.preserveSet<AllAnalysesOn<Loop>>(); - return PA; -} - -INITIALIZE_PASS_BEGIN(JSONExporter, "polly-export-jscop", - "Polly - Export Scops as JSON" - " (Writes a .jscop file for each Scop)", - false, false); -INITIALIZE_PASS_DEPENDENCY(DependenceInfo) -INITIALIZE_PASS_END(JSONExporter, "polly-export-jscop", - "Polly - Export Scops as JSON" - " (Writes a .jscop file for each Scop)", - false, false) - -INITIALIZE_PASS_BEGIN(JSONImporter, "polly-import-jscop", - "Polly - Import Scops from JSON" - " (Reads a .jscop file for each Scop)", - false, false); -INITIALIZE_PASS_DEPENDENCY(DependenceInfo) -INITIALIZE_PASS_END(JSONImporter, "polly-import-jscop", - "Polly - Import Scops from JSON" - " (Reads a .jscop file for each Scop)", - false, false) - -//===----------------------------------------------------------------------===// - -namespace { -/// Print result from JSONImporter. -class JSONImporterPrinterLegacyPass final : public ScopPass { -public: - static char ID; - - JSONImporterPrinterLegacyPass() : JSONImporterPrinterLegacyPass(outs()) {} - explicit JSONImporterPrinterLegacyPass(llvm::raw_ostream &OS) - : ScopPass(ID), OS(OS) {} - - bool runOnScop(Scop &S) override { - JSONImporter &P = getAnalysis<JSONImporter>(); - - OS << "Printing analysis '" << P.getPassName() << "' for region: '" - << S.getRegion().getNameStr() << "' in function '" - << S.getFunction().getName() << "':\n"; - P.printScop(OS, S); - - return false; + if (PollyPrintImportJscop) { + outs() + << "Printing analysis 'Polly - Print Scop import result' for region: '" + << S.getRegion().getNameStr() << "' in function '" + << S.getFunction().getName() << "':\n"; + outs() << S; + for (std::vector<std::string>::const_iterator I = NewAccessStrings.begin(), + E = NewAccessStrings.end(); + I != E; I++) + outs() << "New access function '" << *I << "' detected in JSCOP file\n"; } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<JSONImporter>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char JSONImporterPrinterLegacyPass::ID = 0; -} // namespace - -Pass *polly::createJSONImporterPrinterLegacyPass(llvm::raw_ostream &OS) { - return new JSONImporterPrinterLegacyPass(OS); } -INITIALIZE_PASS_BEGIN(JSONImporterPrinterLegacyPass, "polly-print-import-jscop", - "Polly - Print Scop import result", false, false) -INITIALIZE_PASS_DEPENDENCY(JSONImporter) -INITIALIZE_PASS_END(JSONImporterPrinterLegacyPass, "polly-print-import-jscop", - "Polly - Print Scop import result", false, false) +void polly::runExportJSON(Scop &S) { exportScop(S); } diff --git a/polly/lib/Pass/PhaseManager.cpp b/polly/lib/Pass/PhaseManager.cpp new file mode 100644 index 0000000..330dfe8 --- /dev/null +++ b/polly/lib/Pass/PhaseManager.cpp @@ -0,0 +1,437 @@ +//===------ PhaseManager.cpp ------------------------------------*- 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 +// +//===----------------------------------------------------------------------===// + +#include "polly/Pass/PhaseManager.h" +#include "polly/CodeGen/CodeGeneration.h" +#include "polly/CodeGen/IslAst.h" +#include "polly/CodePreparation.h" +#include "polly/DeLICM.h" +#include "polly/DeadCodeElimination.h" +#include "polly/DependenceInfo.h" +#include "polly/FlattenSchedule.h" +#include "polly/ForwardOpTree.h" +#include "polly/JSONExporter.h" +#include "polly/MaximalStaticExpansion.h" +#include "polly/PruneUnprofitable.h" +#include "polly/ScheduleOptimizer.h" +#include "polly/ScopDetection.h" +#include "polly/ScopDetectionDiagnostic.h" +#include "polly/ScopGraphPrinter.h" +#include "polly/ScopInfo.h" +#include "polly/Simplify.h" +#include "polly/Support/PollyDebug.h" +#include "llvm/ADT/PriorityWorklist.h" +#include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h" +#include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/IR/Module.h" + +#define DEBUG_TYPE "polly-pass" + +using namespace polly; +using namespace llvm; + +namespace { + +/// Recurse through all subregions and all regions and add them to RQ. +static void addRegionIntoQueue(Region &R, SmallVector<Region *> &RQ) { + RQ.push_back(&R); + for (const auto &E : R) + addRegionIntoQueue(*E, RQ); +} + +/// The phase pipeline of Polly to be embedded into another pass manager than +/// runs passes on functions. +/// +/// Polly holds state besides LLVM-IR (RegionInfo and ScopInfo) between phases +/// that LLVM pass managers do not consider when scheduling analyses and passes. +/// That is, the ScopInfo must persist between phases that a pass manager must +/// not invalidate to recompute later. +class PhaseManager { +private: + Function &F; + FunctionAnalysisManager &FAM; + PollyPassOptions Opts; + +public: + PhaseManager(Function &F, FunctionAnalysisManager &FAM, PollyPassOptions Opts) + : F(F), FAM(FAM), Opts(std::move(Opts)) {} + + /// Execute Polly's phases as indicated by the options. + bool run() { + // Get analyses from the function pass manager. + // These must be preserved during all phases so that if processing one SCoP + // has finished, the next SCoP can still use them. Recomputing is not an + // option because ScopDetection stores references to the old results. + // TODO: CodePreparation doesn't actually need these analysis, it just keeps + // them up-to-date. If they are not computed yet, can also compute after the + // prepare phase. + LoopInfo &LI = FAM.getResult<LoopAnalysis>(F); + DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F); + bool ModifiedIR = false; + + // Phase: prepare + // TODO: Setting ModifiedIR will invalidate any analysis, even if DT, LI are + // preserved. + if (Opts.isPhaseEnabled(PassPhase::Prepare)) { + if (runCodePreparation(F, &DT, &LI, nullptr)) { + PreservedAnalyses PA; + PA.preserve<DominatorTreeAnalysis>(); + PA.preserve<LoopAnalysis>(); + FAM.invalidate(F, PA); + ModifiedIR = true; + } + } + + // Can't do anything without detection + if (!Opts.isPhaseEnabled(PassPhase::Detection)) + return false; + + AAResults &AA = FAM.getResult<AAManager>(F); + ScalarEvolution &SE = FAM.getResult<ScalarEvolutionAnalysis>(F); + OptimizationRemarkEmitter &ORE = + FAM.getResult<OptimizationRemarkEmitterAnalysis>(F); + + // ScopDetection is modifying RegionInfo, do not cache it, nor use a cached + // version. + RegionInfo RI = RegionInfoAnalysis().run(F, FAM); + + // Phase: detection + ScopDetection SD(DT, SE, LI, RI, AA, ORE); + SD.detect(F); + if (Opts.isPhaseEnabled(PassPhase::PrintDetect)) { + outs() << "Detected Scops in Function " << F.getName() << "\n"; + for (const Region *R : SD.ValidRegions) + outs() << "Valid Region for Scop: " << R->getNameStr() << '\n'; + outs() << "\n"; + } + + if (Opts.isPhaseEnabled(PassPhase::DotScops)) + printGraphForFunction(F, &SD, "scops", false); + if (Opts.isPhaseEnabled(PassPhase::DotScopsOnly)) + printGraphForFunction(F, &SD, "scopsonly", true); + + auto ViewScops = [&](const char *Name, bool IsSimply) { + if (Opts.ViewFilter.empty() && !F.getName().count(Opts.ViewFilter)) + return; + + if (Opts.ViewAll || std::distance(SD.begin(), SD.end()) > 0) + viewGraphForFunction(F, &SD, Name, IsSimply); + }; + if (Opts.isPhaseEnabled(PassPhase::ViewScops)) + ViewScops("scops", false); + if (Opts.isPhaseEnabled(PassPhase::ViewScopsOnly)) + ViewScops("scopsonly", true); + + // Phase: scops + AssumptionCache &AC = FAM.getResult<AssumptionAnalysis>(F); + const DataLayout &DL = F.getParent()->getDataLayout(); + ScopInfo Info(DL, SD, SE, LI, AA, DT, AC, ORE); + if (Opts.isPhaseEnabled(PassPhase::PrintScopInfo)) { + if (Region *TLR = RI.getTopLevelRegion()) { + SmallVector<Region *> Regions; + addRegionIntoQueue(*TLR, Regions); + + // reverse iteration because the regression tests expect it. + for (Region *R : reverse(Regions)) { + Scop *S = Info.getScop(R); + outs() << "Printing analysis 'Polly - Create polyhedral " + "description of Scops' for region: '" + << R->getNameStr() << "' in function '" << F.getName() + << "':\n"; + if (S) + outs() << *S; + else + outs() << "Invalid Scop!\n"; + } + } + } + + SmallPriorityWorklist<Region *, 4> Worklist; + for (auto &[R, S] : Info) + if (S) + Worklist.insert(R); + + TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F); + while (!Worklist.empty()) { + Region *R = Worklist.pop_back_val(); + Scop *S = Info.getScop(R); + if (!S) { + // This can happen if codegenning of a previous SCoP made this region + // not-a-SCoP anymore. + POLLY_DEBUG(dbgs() << "SCoP in Region '" << *R << "' disappeared"); + continue; + } + + if (!SD.isMaxRegionInScop(*R, /*Verify=*/false)) + continue; + + // Phase: flatten + if (Opts.isPhaseEnabled(PassPhase::Flatten)) + runFlattenSchedulePass(*S); + + // Phase: deps + // Actual analysis runs on-demand, so it does not matter whether the phase + // is actually enabled, but use this location to print dependencies. + DependenceAnalysis::Result DA = runDependenceAnalysis(*S); + if (Opts.isPhaseEnabled(PassPhase::PrintDependences)) { + assert(Opts.isPhaseEnabled(PassPhase::Dependences)); + const Dependences &D = DA.getDependences(Opts.PrintDepsAnalysisLevel); + D.print(outs()); + } + + // Phase: import-jscop + if (Opts.isPhaseEnabled(PassPhase::ImportJScop)) + runImportJSON(*S, DA); + + // Phase: simplify-0 + bool ModifiedSinceSimplify = true; + if (Opts.isPhaseEnabled(PassPhase::Simplify0)) { + runSimplify(*S, 0); + ModifiedSinceSimplify = false; + } + + // Phase: optree + if (Opts.isPhaseEnabled(PassPhase::Optree)) { + bool ModifiedByOptree = runForwardOpTree(*S); + ModifiedSinceSimplify |= ModifiedByOptree; + } + + // Phase: delicm + if (Opts.isPhaseEnabled(PassPhase::DeLICM)) { + bool ModifiedByDelicm = runDeLICM(*S); + ModifiedSinceSimplify |= ModifiedByDelicm; + } + + // Phase: simplify-1 + // If we have already run simplify-0, do not re-run it if the SCoP has not + // changed since then. + if (ModifiedSinceSimplify && Opts.isPhaseEnabled(PassPhase::Simplify1)) { + runSimplify(*S, 1); + ModifiedSinceSimplify = false; + } + + // Phase: dce + if (Opts.isPhaseEnabled(PassPhase::DeadCodeElimination)) + runDeadCodeElim(*S, DA); + + // Phase: mse + if (Opts.isPhaseEnabled(PassPhase::MaximumStaticExtension)) + runMaximalStaticExpansion(*S, DA); + + // Phase: prune + if (Opts.isPhaseEnabled(PassPhase::PruneUnprofitable)) + runPruneUnprofitable(*S); + + // Phase: opt-isl + if (Opts.isPhaseEnabled(PassPhase::Optimization)) + runIslScheduleOptimizer(*S, &TTI, DA); + + // Phase: import-jscop + if (Opts.isPhaseEnabled(PassPhase::ExportJScop)) + runExportJSON(*S); + + // Phase: ast + // Cannot run codegen unless ast is enabled + if (!Opts.isPhaseEnabled(PassPhase::AstGen)) + continue; + std::unique_ptr<IslAstInfo> IslAst = runIslAstGen(*S, DA); + + // Phase: codegen + if (!Opts.isPhaseEnabled(PassPhase::CodeGen)) + continue; + bool ModifiedByCodeGen = runCodeGeneration(*S, RI, *IslAst); + if (ModifiedByCodeGen) { + ModifiedIR = true; + + // For all regions, create new polly::Scop objects because the old ones + // refere to invalidated LLVM-IR. + // FIXME: Adds all SCoPs again to statistics + Info.recompute(); + } + } + + return ModifiedIR; + } +}; +} // namespace + +StringRef polly::getPhaseName(PassPhase Phase) { + switch (Phase) { + case PassPhase::Prepare: + return "prepare"; + case PassPhase::Detection: + return "detect"; + case PassPhase::PrintDetect: + return "print-detect"; + case PassPhase::DotScops: + return "dot-scops"; + case PassPhase::DotScopsOnly: + return "dot-scops-only"; + case PassPhase::ViewScops: + return "view-scops"; + case PassPhase::ViewScopsOnly: + return "view-scops-only"; + case PassPhase::ScopInfo: + return "scops"; + case PassPhase::PrintScopInfo: + return "print-scops"; + case PassPhase::Flatten: + return "flatten"; + case PassPhase::Dependences: + return "deps"; + case PassPhase::PrintDependences: + return "print-deps"; + case PassPhase::ImportJScop: + return "import-jscop"; + case PassPhase::Simplify0: + return "simplify-0"; + case PassPhase::Optree: + return "optree"; + case PassPhase::DeLICM: + return "delicm"; + case PassPhase::Simplify1: + return "simplify-1"; + case PassPhase::DeadCodeElimination: + return "dce"; + case PassPhase::MaximumStaticExtension: + return "mse"; + case PassPhase::PruneUnprofitable: + return "prune"; + case PassPhase::Optimization: + return "opt-isl"; // "opt" would conflict with the llvm executable + case PassPhase::ExportJScop: + return "export-jscop"; + case PassPhase::AstGen: + return "ast"; + case PassPhase::CodeGen: + return "codegen"; + default: + llvm_unreachable("Unexpected phase"); + } +} + +PassPhase polly::parsePhase(StringRef Name) { + return StringSwitch<PassPhase>(Name) + .Case("prepare", PassPhase::Prepare) + .Case("detect", PassPhase::Detection) + .Case("print-detect", PassPhase::PrintDetect) + .Case("dot-scops", PassPhase::DotScops) + .Case("dot-scops-only", PassPhase::DotScopsOnly) + .Case("view-scops", PassPhase::ViewScops) + .Case("view-scops-only", PassPhase::ViewScopsOnly) + .Case("scops", PassPhase::ScopInfo) + .Case("print-scops", PassPhase::PrintScopInfo) + .Case("flatten", PassPhase::Flatten) + .Case("deps", PassPhase::Dependences) + .Case("print-deps", PassPhase::PrintDependences) + .Case("import-jscop", PassPhase::ImportJScop) + .Case("simplify-0", PassPhase::Simplify0) + .Case("optree", PassPhase::Optree) + .Case("delicm", PassPhase::DeLICM) + .Case("simplify-1", PassPhase::Simplify1) + .Case("dce", PassPhase::DeadCodeElimination) + .Case("mse", PassPhase::MaximumStaticExtension) + .Case("prune", PassPhase::PruneUnprofitable) + .Case("opt-isl", PassPhase::Optimization) + .Case("export-jscop", PassPhase::ExportJScop) + .Case("ast", PassPhase::AstGen) + .Case("codegen", PassPhase::CodeGen) + .Default(PassPhase::None); +} + +bool polly::dependsOnDependenceInfo(PassPhase Phase) { + // Nothing before dep phase can depend on it + if (static_cast<size_t>(Phase) <= static_cast<size_t>(PassPhase::Dependences)) + return false; + + switch (Phase) { + case PassPhase::Simplify0: + case PassPhase::Optree: + case PassPhase::DeLICM: + case PassPhase::Simplify1: + case PassPhase::PruneUnprofitable: + case PassPhase::ImportJScop: + case PassPhase::ExportJScop: + case PassPhase::AstGen: // transitively through codegen + case PassPhase::CodeGen: + return false; + default: + return true; + } +} + +void PollyPassOptions::enableEnd2End() { + setPhaseEnabled(PassPhase::Detection); + setPhaseEnabled(PassPhase::ScopInfo); + setPhaseEnabled(PassPhase::Dependences); + setPhaseEnabled(PassPhase::AstGen); + setPhaseEnabled(PassPhase::CodeGen); +} + +void PollyPassOptions::enableDefaultOpts() { + setPhaseEnabled(PassPhase::Prepare); + setPhaseEnabled(PassPhase::Simplify0); + setPhaseEnabled(PassPhase::Optree); + setPhaseEnabled(PassPhase::DeLICM); + setPhaseEnabled(PassPhase::Simplify1); + setPhaseEnabled(PassPhase::PruneUnprofitable); + setPhaseEnabled(PassPhase::Optimization); +} + +void PollyPassOptions::disableAfter(PassPhase Phase) { + assert(Phase != PassPhase::None); + for (PassPhase P : enum_seq_inclusive(Phase, PassPhase::PassPhaseLast)) { + if (P == Phase) + continue; + setPhaseEnabled(P, false); + } +} + +Error PollyPassOptions::checkConsistency() const { + for (PassPhase P : enum_seq_inclusive(PassPhase::PassPhaseFirst, + PassPhase::PassPhaseLast)) { + if (!isPhaseEnabled(P)) + continue; + + // Prepare and Detection have no requirements + if (P == PassPhase::Prepare || P == PassPhase::Detection) + continue; + + if (!isPhaseEnabled(PassPhase::Detection)) + return make_error<StringError>( + formatv("'{0}' requires 'detect' to be enabled", getPhaseName(P)) + .str(), + inconvertibleErrorCode()); + + if (static_cast<size_t>(P) < static_cast<size_t>(PassPhase::ScopInfo)) + continue; + + if (!isPhaseEnabled(PassPhase::ScopInfo)) + return make_error<StringError>( + formatv("'{0}' requires 'scops' to be enabled", getPhaseName(P)) + .str(), + inconvertibleErrorCode()); + + if (dependsOnDependenceInfo(P) && !isPhaseEnabled(PassPhase::Dependences)) + return make_error<StringError>( + formatv("'{0}' requires 'deps' to be enabled", getPhaseName(P)).str(), + inconvertibleErrorCode()); + } + + if (isPhaseEnabled(PassPhase::CodeGen) && !isPhaseEnabled(PassPhase::AstGen)) + return make_error<StringError>("'codegen' requires 'ast' to be enabled", + inconvertibleErrorCode()); + + return Error::success(); +} + +bool polly::runPollyPass(Function &F, FunctionAnalysisManager &FAM, + PollyPassOptions Opts) { + return PhaseManager(F, FAM, std::move(Opts)).run(); +} diff --git a/polly/lib/Pass/PollyFunctionPass.cpp b/polly/lib/Pass/PollyFunctionPass.cpp new file mode 100644 index 0000000..a478e4d --- /dev/null +++ b/polly/lib/Pass/PollyFunctionPass.cpp @@ -0,0 +1,22 @@ +//===------ PollyFunctionPass.cpp - Polly function pass ------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "polly/Pass/PollyFunctionPass.h" + +using namespace llvm; +using namespace polly; + +PreservedAnalyses PollyFunctionPass::run(llvm::Function &F, + llvm::FunctionAnalysisManager &FAM) { + bool ModifiedIR = runPollyPass(F, FAM, Opts); + + // Be conservative about preserved analyses. + // FIXME: May also need to invalidate/update Module/CGSCC passes, but cannot + // reach them within a FunctionPassManager. + return ModifiedIR ? PreservedAnalyses::none() : PreservedAnalyses::all(); +} diff --git a/polly/lib/Pass/PollyModulePass.cpp b/polly/lib/Pass/PollyModulePass.cpp new file mode 100644 index 0000000..f56ee67 --- /dev/null +++ b/polly/lib/Pass/PollyModulePass.cpp @@ -0,0 +1,29 @@ +//===------ PollyModulePass.cpp - Polly module pass ----------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "polly/Pass/PollyModulePass.h" +#include "llvm/IR/Module.h" + +using namespace llvm; +using namespace polly; + +PreservedAnalyses PollyModulePass::run(llvm::Module &M, + llvm::ModuleAnalysisManager &MAM) { + FunctionAnalysisManager &FAM = + MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); + + bool ModifiedAnyIR = false; + for (Function &F : M) { + bool LocalModifiedIR = runPollyPass(F, FAM, Opts); + ModifiedAnyIR |= LocalModifiedIR; + } + + // Be conservative about preserved analyses, especially if parallel functions + // have been outlined. + return ModifiedAnyIR ? PreservedAnalyses::none() : PreservedAnalyses::all(); +} diff --git a/polly/lib/Support/DumpFunctionPass.cpp b/polly/lib/Support/DumpFunctionPass.cpp index e47b7fe..9565e21 100644 --- a/polly/lib/Support/DumpFunctionPass.cpp +++ b/polly/lib/Support/DumpFunctionPass.cpp @@ -13,7 +13,6 @@ #include "polly/Support/DumpFunctionPass.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassInstrumentation.h" -#include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -82,50 +81,10 @@ static void runDumpFunction(llvm::Function &F, StringRef Suffix) { Out->keep(); LLVM_DEBUG(dbgs() << "Dump file " << Dumpfile << " written successfully\n"); } - -class DumpFunctionWrapperPass final : public FunctionPass { -private: - DumpFunctionWrapperPass(const DumpFunctionWrapperPass &) = delete; - const DumpFunctionWrapperPass & - operator=(const DumpFunctionWrapperPass &) = delete; - - std::string Suffix; - -public: - static char ID; - - explicit DumpFunctionWrapperPass() : FunctionPass(ID), Suffix("-dump") {} - - explicit DumpFunctionWrapperPass(std::string Suffix) - : FunctionPass(ID), Suffix(std::move(Suffix)) {} - - /// @name FunctionPass interface - //@{ - void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - - bool runOnFunction(llvm::Function &F) override { - runDumpFunction(F, Suffix); - return false; - } - //@} -}; - -char DumpFunctionWrapperPass::ID; } // namespace -FunctionPass *polly::createDumpFunctionWrapperPass(std::string Suffix) { - return new DumpFunctionWrapperPass(std::move(Suffix)); -} - llvm::PreservedAnalyses DumpFunctionPass::run(Function &F, FunctionAnalysisManager &AM) { runDumpFunction(F, Suffix); return PreservedAnalyses::all(); } - -INITIALIZE_PASS_BEGIN(DumpFunctionWrapperPass, "polly-dump-function", - "Polly - Dump Function", false, false) -INITIALIZE_PASS_END(DumpFunctionWrapperPass, "polly-dump-function", - "Polly - Dump Function", false, false) diff --git a/polly/lib/Support/DumpModulePass.cpp b/polly/lib/Support/DumpModulePass.cpp index c1c27ef..2eaa070 100644 --- a/polly/lib/Support/DumpModulePass.cpp +++ b/polly/lib/Support/DumpModulePass.cpp @@ -12,7 +12,6 @@ #include "polly/Support/DumpModulePass.h" #include "llvm/IR/Module.h" -#include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -47,56 +46,10 @@ static void runDumpModule(llvm::Module &M, StringRef Filename, bool IsSuffix) { M.print(Out->os(), nullptr); Out->keep(); } - -class DumpModuleWrapperPass final : public ModulePass { -private: - DumpModuleWrapperPass(const DumpModuleWrapperPass &) = delete; - const DumpModuleWrapperPass & - operator=(const DumpModuleWrapperPass &) = delete; - - std::string Filename; - bool IsSuffix; - -public: - static char ID; - - /// This constructor is used e.g. if using opt -polly-dump-module. - /// - /// Provide a default suffix to not overwrite the original file. - explicit DumpModuleWrapperPass() - : ModulePass(ID), Filename("-dump"), IsSuffix(true) {} - - explicit DumpModuleWrapperPass(std::string Filename, bool IsSuffix) - : ModulePass(ID), Filename(std::move(Filename)), IsSuffix(IsSuffix) {} - - /// @name ModulePass interface - //@{ - void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } - - bool runOnModule(llvm::Module &M) override { - runDumpModule(M, Filename, IsSuffix); - return false; - } - //@} -}; - -char DumpModuleWrapperPass::ID; } // namespace -ModulePass *polly::createDumpModuleWrapperPass(std::string Filename, - bool IsSuffix) { - return new DumpModuleWrapperPass(std::move(Filename), IsSuffix); -} - llvm::PreservedAnalyses DumpModulePass::run(llvm::Module &M, llvm::ModuleAnalysisManager &AM) { runDumpModule(M, Filename, IsSuffix); return PreservedAnalyses::all(); } - -INITIALIZE_PASS_BEGIN(DumpModuleWrapperPass, "polly-dump-module", - "Polly - Dump Module", false, false) -INITIALIZE_PASS_END(DumpModuleWrapperPass, "polly-dump-module", - "Polly - Dump Module", false, false) diff --git a/polly/lib/Support/PollyPasses.def b/polly/lib/Support/PollyPasses.def index 2c792a5..c95ffa3 100644 --- a/polly/lib/Support/PollyPasses.def +++ b/polly/lib/Support/PollyPasses.def @@ -1,54 +1,19 @@ +#ifndef MODULE_PASS +#define MODULE_PASS(NAME, CREATE_PASS, PARSER) +#endif +MODULE_PASS("polly", createModuleToFunctionPassAdaptor(PollyFunctionPass(Opts)), parsePollyDefaultOptions) +MODULE_PASS("polly-custom", createModuleToFunctionPassAdaptor(PollyFunctionPass(Opts)), parsePollyCustomOptions) +#undef MODULE_PASS + #ifndef CGSCC_PASS #define CGSCC_PASS(NAME, CREATE_PASS, PARSER) #endif CGSCC_PASS("polly-inline", ScopInlinerPass(), parseNoOptions) #undef CGSCC_PASS -#ifndef FUNCTION_ANALYSIS -#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) -#endif -FUNCTION_ANALYSIS("polly-detect", ScopAnalysis()) -FUNCTION_ANALYSIS("polly-function-scops", ScopInfoAnalysis()) -#undef FUNCTION_ANALYSIS - #ifndef FUNCTION_PASS -#define FUNCTION_PASS(NAME, CREATE_PASS) +#define FUNCTION_PASS(NAME, CREATE_PASS, PARSER) #endif -FUNCTION_PASS("polly-prepare", CodePreparationPass()) -FUNCTION_PASS("print<polly-detect>", ScopAnalysisPrinterPass(llvm::errs())) -FUNCTION_PASS("print<polly-function-scops>", ScopInfoPrinterPass(llvm::errs())) -FUNCTION_PASS("polly-scop-viewer", ScopViewer()) -FUNCTION_PASS("polly-scop-only-viewer", ScopOnlyViewer()) -FUNCTION_PASS("polly-scop-printer", ScopPrinter()) -FUNCTION_PASS("polly-scop-only-printer", ScopOnlyPrinter()) +FUNCTION_PASS("polly", PollyFunctionPass(Opts), parsePollyDefaultOptions) +FUNCTION_PASS("polly-custom", PollyFunctionPass(Opts), parsePollyCustomOptions) #undef FUNCTION_PASS - -#ifndef SCOP_ANALYSIS -#define SCOP_ANALYSIS(NAME, CREATE_PASS) -#endif -SCOP_ANALYSIS("pass-instrumentation", llvm::PassInstrumentationAnalysis(PIC)) -SCOP_ANALYSIS("polly-ast", IslAstAnalysis()) -SCOP_ANALYSIS("polly-dependences", DependenceAnalysis()) -#undef SCOP_ANALYSIS - -#ifndef SCOP_PASS -#define SCOP_PASS(NAME, CREATE_PASS) -#endif -SCOP_PASS("polly-export-jscop", JSONExportPass()) -SCOP_PASS("polly-import-jscop", JSONImportPass()) -SCOP_PASS("print<polly-ast>", IslAstPrinterPass(llvm::outs())) -SCOP_PASS("print<polly-dependences>", DependenceInfoPrinterPass(llvm::outs())) -SCOP_PASS("polly-codegen", CodeGenerationPass()) -SCOP_PASS("polly-simplify", SimplifyPass()) -SCOP_PASS("print<polly-simplify>", SimplifyPrinterPass(llvm::outs())) -SCOP_PASS("polly-optree", ForwardOpTreePass()) -SCOP_PASS("print<polly-optree>", ForwardOpTreePrinterPass(llvm::outs())) -SCOP_PASS("polly-delicm", DeLICMPass()) -SCOP_PASS("print<polly-delicm>", DeLICMPrinterPass(llvm::outs())) -SCOP_PASS("polly-prune-unprofitable", PruneUnprofitablePass()) -SCOP_PASS("polly-opt-isl", IslScheduleOptimizerPass()) -SCOP_PASS("print<polly-opt-isl>", IslScheduleOptimizerPrinterPass(llvm::outs())) -SCOP_PASS("polly-dce", DeadCodeElimPass()) -SCOP_PASS("polly-mse", MaximalStaticExpansionPass()) -SCOP_PASS("print<polly-mse>", MaximalStaticExpansionPrinterPass(llvm::outs())) -#undef SCOP_PASS diff --git a/polly/lib/Support/RegisterPasses.cpp b/polly/lib/Support/RegisterPasses.cpp index 04f8715..a430bee 100644 --- a/polly/lib/Support/RegisterPasses.cpp +++ b/polly/lib/Support/RegisterPasses.cpp @@ -28,8 +28,9 @@ #include "polly/DependenceInfo.h" #include "polly/ForwardOpTree.h" #include "polly/JSONExporter.h" -#include "polly/LinkAllPasses.h" #include "polly/MaximalStaticExpansion.h" +#include "polly/Options.h" +#include "polly/Pass/PollyFunctionPass.h" #include "polly/PruneUnprofitable.h" #include "polly/ScheduleOptimizer.h" #include "polly/ScopDetection.h" @@ -52,6 +53,8 @@ #include "llvm/Transforms/IPO.h" using namespace llvm; +using namespace polly; + namespace cl = llvm::cl; using namespace polly; @@ -201,58 +204,19 @@ static cl::opt<bool> EnablePruneUnprofitable( cl::desc("Bail out on unprofitable SCoPs before rescheduling"), cl::Hidden, cl::init(true), cl::cat(PollyCategory)); -namespace { +static cl::opt<bool> + PollyPrintDetect("polly-print-detect", + cl::desc("Polly - Print static control parts (SCoPs)"), + cl::cat(PollyCategory)); -/// Initialize Polly passes when library is loaded. -/// -/// We use the constructor of a statically declared object to initialize the -/// different Polly passes right after the Polly library is loaded. This ensures -/// that the Polly passes are available e.g. in the 'opt' tool. -struct StaticInitializer { - StaticInitializer() { - llvm::PassRegistry &Registry = *llvm::PassRegistry::getPassRegistry(); - polly::initializePollyPasses(Registry); - } -}; -static StaticInitializer InitializeEverything; -} // end of anonymous namespace. - -void initializePollyPasses(llvm::PassRegistry &Registry) { - initializeCodeGenerationPass(Registry); - - initializeCodePreparationPass(Registry); - initializeDeadCodeElimWrapperPassPass(Registry); - initializeDependenceInfoPass(Registry); - initializeDependenceInfoPrinterLegacyPassPass(Registry); - initializeDependenceInfoWrapperPassPass(Registry); - initializeDependenceInfoPrinterLegacyFunctionPassPass(Registry); - initializeJSONExporterPass(Registry); - initializeJSONImporterPass(Registry); - initializeJSONImporterPrinterLegacyPassPass(Registry); - initializeMaximalStaticExpanderWrapperPassPass(Registry); - initializeIslAstInfoWrapperPassPass(Registry); - initializeIslAstInfoPrinterLegacyPassPass(Registry); - initializeIslScheduleOptimizerWrapperPassPass(Registry); - initializeIslScheduleOptimizerPrinterLegacyPassPass(Registry); - initializePollyCanonicalizePass(Registry); - initializeScopDetectionWrapperPassPass(Registry); - initializeScopDetectionPrinterLegacyPassPass(Registry); - initializeScopInlinerWrapperPassPass(Registry); - initializeScopInfoRegionPassPass(Registry); - initializeScopInfoPrinterLegacyRegionPassPass(Registry); - initializeScopInfoWrapperPassPass(Registry); - initializeScopInfoPrinterLegacyFunctionPassPass(Registry); - initializeFlattenSchedulePass(Registry); - initializeFlattenSchedulePrinterLegacyPassPass(Registry); - initializeForwardOpTreeWrapperPassPass(Registry); - initializeForwardOpTreePrinterLegacyPassPass(Registry); - initializeDeLICMWrapperPassPass(Registry); - initializeDeLICMPrinterLegacyPassPass(Registry); - initializeSimplifyWrapperPassPass(Registry); - initializeSimplifyPrinterLegacyPassPass(Registry); - initializeDumpModuleWrapperPassPass(Registry); - initializePruneUnprofitableWrapperPassPass(Registry); -} +static cl::opt<bool> + PollyPrintScops("polly-print-scops", + cl::desc("Print polyhedral description of all regions"), + cl::cat(PollyCategory)); + +static cl::opt<bool> PollyPrintDeps("polly-print-deps", + cl::desc("Polly - Print dependences"), + cl::cat(PollyCategory)); static bool shouldEnablePollyForOptimization() { return PollyEnabled; } @@ -266,6 +230,198 @@ static bool shouldEnablePollyForDiagnostic() { ExportJScop; } +/// Parser of parameters for LoopVectorize pass. +static llvm::Expected<PollyPassOptions> parsePollyOptions(StringRef Params, + bool IsCustom) { + PassPhase PrevPhase = PassPhase::None; + + bool EnableDefaultOpts = !IsCustom; + bool EnableEnd2End = !IsCustom; + std::optional<bool> + PassEnabled[static_cast<size_t>(PassPhase::PassPhaseLast) + 1]; + PassPhase StopAfter = PassPhase::None; + + // Passes enabled using command-line flags (can be overridden using + // 'polly<no-pass>') + if (PollyPrintDetect) + PassEnabled[static_cast<size_t>(PassPhase::PrintDetect)] = true; + if (PollyPrintScops) + PassEnabled[static_cast<size_t>(PassPhase::PrintScopInfo)] = true; + if (PollyPrintDeps) + PassEnabled[static_cast<size_t>(PassPhase::PrintDependences)] = true; + + if (PollyViewer) + PassEnabled[static_cast<size_t>(PassPhase::ViewScops)] = true; + if (PollyOnlyViewer) + PassEnabled[static_cast<size_t>(PassPhase::ViewScopsOnly)] = true; + if (PollyPrinter) + PassEnabled[static_cast<size_t>(PassPhase::DotScops)] = true; + if (PollyOnlyPrinter) + PassEnabled[static_cast<size_t>(PassPhase::DotScopsOnly)] = true; + if (!EnableSimplify) + PassEnabled[static_cast<size_t>(PassPhase::Simplify0)] = false; + if (!EnableForwardOpTree) + PassEnabled[static_cast<size_t>(PassPhase::Optree)] = false; + if (!EnableDeLICM) + PassEnabled[static_cast<size_t>(PassPhase::DeLICM)] = false; + if (!EnableSimplify) + PassEnabled[static_cast<size_t>(PassPhase::Simplify1)] = false; + if (ImportJScop) + PassEnabled[static_cast<size_t>(PassPhase::ImportJScop)] = true; + if (DeadCodeElim) + PassEnabled[static_cast<size_t>(PassPhase::DeadCodeElimination)] = true; + if (FullyIndexedStaticExpansion) + PassEnabled[static_cast<size_t>(PassPhase::MaximumStaticExtension)] = true; + if (!EnablePruneUnprofitable) + PassEnabled[static_cast<size_t>(PassPhase::PruneUnprofitable)] = false; + switch (Optimizer) { + case OPTIMIZER_NONE: + // explicitly switched off + PassEnabled[static_cast<size_t>(PassPhase::Optimization)] = false; + break; + case OPTIMIZER_ISL: + // default: enabled + break; + } + if (ExportJScop) + PassEnabled[static_cast<size_t>(PassPhase::ExportJScop)] = true; + switch (CodeGeneration) { + case CODEGEN_AST: + PassEnabled[static_cast<size_t>(PassPhase::AstGen)] = true; + PassEnabled[static_cast<size_t>(PassPhase::CodeGen)] = false; + break; + case CODEGEN_FULL: + // default: ast and codegen enabled + break; + case CODEGEN_NONE: + PassEnabled[static_cast<size_t>(PassPhase::AstGen)] = false; + PassEnabled[static_cast<size_t>(PassPhase::CodeGen)] = false; + break; + } + + while (!Params.empty()) { + StringRef Param; + std::tie(Param, Params) = Params.split(';'); + auto [ParamName, ParamVal] = Param.split('='); + + if (ParamName == "stopafter") { + StopAfter = parsePhase(ParamVal); + if (StopAfter == PassPhase::None) + return make_error<StringError>( + formatv("invalid stopafter parameter value '{0}'", ParamVal).str(), + inconvertibleErrorCode()); + continue; + } + + if (!ParamVal.empty()) + return make_error<StringError>( + formatv("parameter '{0}' does not take value", ParamName).str(), + inconvertibleErrorCode()); + + bool Enabled = true; + if (ParamName.starts_with("no-")) { + Enabled = false; + ParamName = ParamName.drop_front(3); + } + + if (ParamName == "default-opts") { + EnableDefaultOpts = Enabled; + continue; + } + + if (ParamName == "end2end") { + EnableEnd2End = Enabled; + continue; + } + + PassPhase Phase; + + // Shortcut for both simplifys at the same time + if (ParamName == "simplify") { + PassEnabled[static_cast<size_t>(PassPhase::Simplify0)] = Enabled; + PassEnabled[static_cast<size_t>(PassPhase::Simplify1)] = Enabled; + Phase = PassPhase::Simplify0; + } else { + Phase = parsePhase(ParamName); + if (Phase == PassPhase::None) + return make_error<StringError>( + formatv("invalid Polly parameter/phase name '{0}'", ParamName) + .str(), + inconvertibleErrorCode()); + + if (PrevPhase >= Phase) + return make_error<StringError>( + formatv("phases must not be repeated and enumerated in-order: " + "'{0}' listed before '{1}'", + getPhaseName(PrevPhase), getPhaseName(Phase)) + .str(), + inconvertibleErrorCode()); + + PassEnabled[static_cast<size_t>(Phase)] = Enabled; + } + PrevPhase = Phase; + } + + PollyPassOptions Opts; + Opts.ViewAll = ViewAll; + Opts.ViewFilter = ViewFilter; + Opts.PrintDepsAnalysisLevel = OptAnalysisLevel; + + // Implicitly enable dependent phases first. May be overriden explicitly + // on/off later. + for (PassPhase P : llvm::enum_seq_inclusive(PassPhase::PassPhaseFirst, + PassPhase::PassPhaseLast)) { + bool Enabled = PassEnabled[static_cast<size_t>(P)].value_or(false); + if (!Enabled) + continue; + + if (static_cast<size_t>(PassPhase::Detection) < static_cast<size_t>(P)) + Opts.setPhaseEnabled(PassPhase::Detection); + + if (static_cast<size_t>(PassPhase::ScopInfo) < static_cast<size_t>(P)) + Opts.setPhaseEnabled(PassPhase::ScopInfo); + + if (dependsOnDependenceInfo(P)) + Opts.setPhaseEnabled(PassPhase::Dependences); + + if (static_cast<size_t>(PassPhase::AstGen) < static_cast<size_t>(P)) + Opts.setPhaseEnabled(PassPhase::AstGen); + } + + if (EnableEnd2End) + Opts.enableEnd2End(); + + if (EnableDefaultOpts) + Opts.enableDefaultOpts(); + + for (PassPhase P : llvm::enum_seq_inclusive(PassPhase::PassPhaseFirst, + PassPhase::PassPhaseLast)) { + std::optional<bool> Enabled = PassEnabled[static_cast<size_t>(P)]; + + // Apply only if set explicitly. + if (Enabled.has_value()) + Opts.setPhaseEnabled(P, *Enabled); + } + + if (StopAfter != PassPhase::None) + Opts.disableAfter(StopAfter); + + if (Error CheckResult = Opts.checkConsistency()) + return CheckResult; + + return Opts; +} + +static llvm::Expected<PollyPassOptions> +parsePollyDefaultOptions(StringRef Params) { + return parsePollyOptions(Params, false); +} + +static llvm::Expected<PollyPassOptions> +parsePollyCustomOptions(StringRef Params) { + return parsePollyOptions(Params, true); +} + /// Register Polly passes such that they form a polyhedral optimizer. /// /// The individual Polly passes are registered in the pass manager such that @@ -305,77 +461,12 @@ static void buildCommonPollyPipeline(FunctionPassManager &PM, OptimizationLevel Level, bool EnableForOpt) { PassBuilder PB; - ScopPassManager SPM; - PM.addPass(CodePreparationPass()); + ExitOnError Err("Inconsistent Polly configuration: "); + PollyPassOptions &&Opts = + Err(parsePollyOptions(StringRef(), /*IsCustom=*/false)); + PM.addPass(PollyFunctionPass(Opts)); - // TODO add utility passes for the various command line options, once they're - // ported - - if (PollyDetectOnly) { - // Don't add more passes other than the ScopPassManager's detection passes. - PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); - return; - } - - if (PollyViewer) - PM.addPass(ScopViewer()); - if (PollyOnlyViewer) - PM.addPass(ScopOnlyViewer()); - if (PollyPrinter) - PM.addPass(ScopPrinter()); - if (PollyOnlyPrinter) - PM.addPass(ScopOnlyPrinter()); - if (EnableSimplify) - SPM.addPass(SimplifyPass(0)); - if (EnableForwardOpTree) - SPM.addPass(ForwardOpTreePass()); - if (EnableDeLICM) - SPM.addPass(DeLICMPass()); - if (EnableSimplify) - SPM.addPass(SimplifyPass(1)); - - if (ImportJScop) - SPM.addPass(JSONImportPass()); - - if (DeadCodeElim) - SPM.addPass(DeadCodeElimPass()); - - if (FullyIndexedStaticExpansion) - SPM.addPass(MaximalStaticExpansionPass()); - - if (EnablePruneUnprofitable) - SPM.addPass(PruneUnprofitablePass()); - - switch (Optimizer) { - case OPTIMIZER_NONE: - break; /* Do nothing */ - case OPTIMIZER_ISL: - SPM.addPass(IslScheduleOptimizerPass()); - break; - } - - if (ExportJScop) - SPM.addPass(JSONExportPass()); - - if (!EnableForOpt) - return; - - switch (CodeGeneration) { - case CODEGEN_AST: - SPM.addPass( - llvm::RequireAnalysisPass<IslAstAnalysis, Scop, ScopAnalysisManager, - ScopStandardAnalysisResults &, - SPMUpdater &>()); - break; - case CODEGEN_FULL: - SPM.addPass(CodeGenerationPass()); - break; - case CODEGEN_NONE: - break; - } - - PM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); PM.addPass(PB.buildFunctionSimplificationPipeline( Level, llvm::ThinOrFullLTOPhase::None)); // Cleanup @@ -448,33 +539,6 @@ static llvm::Expected<std::monostate> parseNoOptions(StringRef Params) { return std::monostate{}; } -static OwningScopAnalysisManagerFunctionProxy -createScopAnalyses(FunctionAnalysisManager &FAM, - PassInstrumentationCallbacks *PIC) { - OwningScopAnalysisManagerFunctionProxy Proxy; -#define SCOP_ANALYSIS(NAME, CREATE_PASS) \ - Proxy.getManager().registerPass([PIC] { \ - (void)PIC; \ - return CREATE_PASS; \ - }); -#include "PollyPasses.def" - - Proxy.getManager().registerPass( - [&FAM] { return FunctionAnalysisManagerScopProxy(FAM); }); - return Proxy; -} - -static void registerFunctionAnalyses(FunctionAnalysisManager &FAM, - PassInstrumentationCallbacks *PIC) { - -#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ - FAM.registerPass([] { return CREATE_PASS; }); - -#include "PollyPasses.def" - - FAM.registerPass([&FAM, PIC] { return createScopAnalyses(FAM, PIC); }); -} - static llvm::Expected<bool> parseCGPipeline(StringRef Name, llvm::CGSCCPassManager &CGPM, PassInstrumentationCallbacks *PIC, @@ -492,21 +556,18 @@ parseCGPipeline(StringRef Name, llvm::CGSCCPassManager &CGPM, return false; } -static bool +static llvm::Expected<bool> parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM, + PassInstrumentationCallbacks *PIC, ArrayRef<PassBuilder::PipelineElement> Pipeline) { - if (llvm::parseAnalysisUtilityPasses<OwningScopAnalysisManagerFunctionProxy>( - "polly-scop-analyses", Name, FPM)) - return true; - -#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ - if (llvm::parseAnalysisUtilityPasses< \ - std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name, \ - FPM)) \ - return true; - -#define FUNCTION_PASS(NAME, CREATE_PASS) \ - if (Name == NAME) { \ + +#define FUNCTION_PASS(NAME, CREATE_PASS, PARSER) \ + if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \ + auto ExpectedOpts = PassBuilder::parsePassParameters(PARSER, Name, NAME); \ + if (!ExpectedOpts) \ + return ExpectedOpts.takeError(); \ + auto &&Opts = *ExpectedOpts; \ + (void)Opts; \ FPM.addPass(CREATE_PASS); \ return true; \ } @@ -515,17 +576,18 @@ parseFunctionPipeline(StringRef Name, FunctionPassManager &FPM, return false; } -static bool parseScopPass(StringRef Name, ScopPassManager &SPM, - PassInstrumentationCallbacks *PIC) { -#define SCOP_ANALYSIS(NAME, CREATE_PASS) \ - if (llvm::parseAnalysisUtilityPasses< \ - std::remove_reference<decltype(CREATE_PASS)>::type>(NAME, Name, \ - SPM)) \ - return true; - -#define SCOP_PASS(NAME, CREATE_PASS) \ - if (Name == NAME) { \ - SPM.addPass(CREATE_PASS); \ +static llvm::Expected<bool> +parseModulePipeline(StringRef Name, llvm::ModulePassManager &MPM, + PassInstrumentationCallbacks *PIC, + ArrayRef<PassBuilder::PipelineElement> Pipeline) { +#define MODULE_PASS(NAME, CREATE_PASS, PARSER) \ + if (PassBuilder::checkParametrizedPassName(Name, NAME)) { \ + auto ExpectedOpts = PassBuilder::parsePassParameters(PARSER, Name, NAME); \ + if (!ExpectedOpts) \ + return ExpectedOpts.takeError(); \ + auto &&Opts = *ExpectedOpts; \ + (void)Opts; \ + MPM.addPass(CREATE_PASS); \ return true; \ } @@ -534,64 +596,6 @@ static bool parseScopPass(StringRef Name, ScopPassManager &SPM, return false; } -static bool parseScopPipeline(StringRef Name, FunctionPassManager &FPM, - PassInstrumentationCallbacks *PIC, - ArrayRef<PassBuilder::PipelineElement> Pipeline) { - if (Name != "scop") - return false; - if (!Pipeline.empty()) { - ScopPassManager SPM; - for (const auto &E : Pipeline) - if (!parseScopPass(E.Name, SPM, PIC)) - return false; - FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); - } - return true; -} - -static bool isScopPassName(StringRef Name) { -#define SCOP_ANALYSIS(NAME, CREATE_PASS) \ - if (Name == "require<" NAME ">") \ - return true; \ - if (Name == "invalidate<" NAME ">") \ - return true; - -#define SCOP_PASS(NAME, CREATE_PASS) \ - if (Name == NAME) \ - return true; - -#include "PollyPasses.def" - - return false; -} - -static bool -parseTopLevelPipeline(llvm::ModulePassManager &MPM, - PassInstrumentationCallbacks *PIC, - ArrayRef<PassBuilder::PipelineElement> Pipeline) { - StringRef FirstName = Pipeline.front().Name; - - if (!isScopPassName(FirstName)) - return false; - - FunctionPassManager FPM; - ScopPassManager SPM; - - for (auto &Element : Pipeline) { - auto &Name = Element.Name; - auto &InnerPipeline = Element.InnerPipeline; - if (!InnerPipeline.empty()) // Scop passes don't have inner pipelines - return false; - if (!parseScopPass(Name, SPM, PIC)) - return false; - } - - FPM.addPass(createFunctionToScopPassAdaptor(std::move(SPM))); - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - - return true; -} - /// Register Polly to be available as an optimizer /// /// @@ -620,14 +624,32 @@ parseTopLevelPipeline(llvm::ModulePassManager &MPM, /// handle LICMed code to make it useful. void registerPollyPasses(PassBuilder &PB) { PassInstrumentationCallbacks *PIC = PB.getPassInstrumentationCallbacks(); - PB.registerAnalysisRegistrationCallback([PIC](FunctionAnalysisManager &FAM) { - registerFunctionAnalyses(FAM, PIC); - }); - PB.registerPipelineParsingCallback(parseFunctionPipeline); + +#define MODULE_PASS(NAME, CREATE_PASS, PARSER) \ + { \ + std::remove_reference_t<decltype(*PARSER(StringRef()))> Opts; \ + (void)Opts; \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); \ + } +#define CGSCC_PASS(NAME, CREATE_PASS, PARSER) \ + { \ + std::remove_reference_t<decltype(*PARSER(StringRef()))> Opts; \ + (void)Opts; \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); \ + } +#define FUNCTION_PASS(NAME, CREATE_PASS, PARSER) \ + { \ + std::remove_reference_t<decltype(*PARSER(StringRef()))> Opts; \ + (void)Opts; \ + PIC->addClassToPassName(decltype(CREATE_PASS)::name(), NAME); \ + } +#include "PollyPasses.def" + PB.registerPipelineParsingCallback( [PIC](StringRef Name, FunctionPassManager &FPM, ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool { - return parseScopPipeline(Name, FPM, PIC, Pipeline); + ExitOnError Err("Unable to parse Polly module pass: "); + return Err(parseFunctionPipeline(Name, FPM, PIC, Pipeline)); }); PB.registerPipelineParsingCallback( [PIC](StringRef Name, CGSCCPassManager &CGPM, @@ -635,10 +657,11 @@ void registerPollyPasses(PassBuilder &PB) { ExitOnError Err("Unable to parse Polly call graph pass: "); return Err(parseCGPipeline(Name, CGPM, PIC, Pipeline)); }); - PB.registerParseTopLevelPipelineCallback( - [PIC](llvm::ModulePassManager &MPM, + PB.registerPipelineParsingCallback( + [PIC](StringRef Name, ModulePassManager &MPM, ArrayRef<PassBuilder::PipelineElement> Pipeline) -> bool { - return parseTopLevelPipeline(MPM, PIC, Pipeline); + ExitOnError Err("Unable to parse Polly module pass: "); + return Err(parseModulePipeline(Name, MPM, PIC, Pipeline)); }); switch (PassPosition) { diff --git a/polly/lib/Support/ScopHelper.cpp b/polly/lib/Support/ScopHelper.cpp index a2328d1..cf0ec44 100644 --- a/polly/lib/Support/ScopHelper.cpp +++ b/polly/lib/Support/ScopHelper.cpp @@ -206,18 +206,6 @@ void polly::splitEntryBlockForAlloca(BasicBlock *EntryBlock, DominatorTree *DT, splitBlock(EntryBlock, I, DT, LI, RI); } -void polly::splitEntryBlockForAlloca(BasicBlock *EntryBlock, Pass *P) { - auto *DTWP = P->getAnalysisIfAvailable<DominatorTreeWrapperPass>(); - auto *DT = DTWP ? &DTWP->getDomTree() : nullptr; - auto *LIWP = P->getAnalysisIfAvailable<LoopInfoWrapperPass>(); - auto *LI = LIWP ? &LIWP->getLoopInfo() : nullptr; - RegionInfoPass *RIP = P->getAnalysisIfAvailable<RegionInfoPass>(); - RegionInfo *RI = RIP ? &RIP->getRegionInfo() : nullptr; - - // splitBlock updates DT, LI and RI. - polly::splitEntryBlockForAlloca(EntryBlock, DT, LI, RI); -} - void polly::recordAssumption(polly::RecordedAssumptionsTy *RecordedAssumptions, polly::AssumptionKind Kind, isl::set Set, DebugLoc Loc, polly::AssumptionSign Sign, diff --git a/polly/lib/Transform/Canonicalization.cpp b/polly/lib/Transform/Canonicalization.cpp index 1be560e..cd7195f 100644 --- a/polly/lib/Transform/Canonicalization.cpp +++ b/polly/lib/Transform/Canonicalization.cpp @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// #include "polly/Canonicalization.h" -#include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/ProfileSummaryInfo.h" @@ -39,24 +38,6 @@ static cl::opt<bool> cl::desc("Run an early inliner pass before Polly"), cl::Hidden, cl::cat(PollyCategory)); -void polly::registerCanonicalicationPasses(llvm::legacy::PassManagerBase &PM) { - bool UseMemSSA = true; - PM.add(llvm::createPromoteMemoryToRegisterPass()); - PM.add(llvm::createEarlyCSEPass(UseMemSSA)); - PM.add(llvm::createInstructionCombiningPass()); - PM.add(llvm::createCFGSimplificationPass()); - PM.add(llvm::createTailCallEliminationPass()); - PM.add(llvm::createCFGSimplificationPass()); - PM.add(llvm::createReassociatePass()); - if (PollyInliner) { - PM.add(llvm::createPromoteMemoryToRegisterPass()); - PM.add(llvm::createCFGSimplificationPass()); - PM.add(llvm::createInstructionCombiningPass()); - PM.add(createBarrierNoopPass()); - } - PM.add(llvm::createInstructionCombiningPass()); -} - /// Adapted from llvm::PassBuilder::buildInlinerPipeline static ModuleInlinerWrapperPass buildInlinePasses(llvm::OptimizationLevel Level) { @@ -125,49 +106,3 @@ polly::buildCanonicalicationPassesForNPM(llvm::ModulePassManager &MPM, return FPM; } - -namespace { -class PollyCanonicalize final : public ModulePass { - PollyCanonicalize(const PollyCanonicalize &) = delete; - const PollyCanonicalize &operator=(const PollyCanonicalize &) = delete; - -public: - static char ID; - - explicit PollyCanonicalize() : ModulePass(ID) {} - ~PollyCanonicalize(); - - /// @name FunctionPass interface. - //@{ - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() override; - bool runOnModule(Module &M) override; - void print(raw_ostream &OS, const Module *) const override; - //@} -}; -} // namespace - -PollyCanonicalize::~PollyCanonicalize() {} - -void PollyCanonicalize::getAnalysisUsage(AnalysisUsage &AU) const {} - -void PollyCanonicalize::releaseMemory() {} - -bool PollyCanonicalize::runOnModule(Module &M) { - legacy::PassManager PM; - registerCanonicalicationPasses(PM); - PM.run(M); - - return true; -} - -void PollyCanonicalize::print(raw_ostream &OS, const Module *) const {} - -char PollyCanonicalize::ID = 0; - -Pass *polly::createPollyCanonicalizePass() { return new PollyCanonicalize(); } - -INITIALIZE_PASS_BEGIN(PollyCanonicalize, "polly-canonicalize", - "Polly - Run canonicalization passes", false, false) -INITIALIZE_PASS_END(PollyCanonicalize, "polly-canonicalize", - "Polly - Run canonicalization passes", false, false) diff --git a/polly/lib/Transform/CodePreparation.cpp b/polly/lib/Transform/CodePreparation.cpp index d045fb6..3e76dbd 100644 --- a/polly/lib/Transform/CodePreparation.cpp +++ b/polly/lib/Transform/CodePreparation.cpp @@ -16,13 +16,11 @@ //===----------------------------------------------------------------------===// #include "polly/CodePreparation.h" -#include "polly/LinkAllPasses.h" #include "polly/Support/ScopHelper.h" #include "llvm/Analysis/DominanceFrontier.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/ScalarEvolution.h" -#include "llvm/InitializePasses.h" using namespace llvm; using namespace polly; @@ -47,83 +45,7 @@ static bool runCodePreprationImpl(Function &F, DominatorTree *DT, LoopInfo *LI, return true; } -namespace { - -/// Prepare the IR for the scop detection. -/// -class CodePreparation final : public FunctionPass { - CodePreparation(const CodePreparation &) = delete; - const CodePreparation &operator=(const CodePreparation &) = delete; - - void clear(); - -public: - static char ID; - - explicit CodePreparation() : FunctionPass(ID) {} - ~CodePreparation(); - - /// @name FunctionPass interface. - //@{ - void getAnalysisUsage(AnalysisUsage &AU) const override; - void releaseMemory() override; - bool runOnFunction(Function &F) override; - void print(raw_ostream &OS, const Module *) const override; - //@} -}; -} // namespace - -PreservedAnalyses CodePreparationPass::run(Function &F, - FunctionAnalysisManager &FAM) { - auto &DT = FAM.getResult<DominatorTreeAnalysis>(F); - auto &LI = FAM.getResult<LoopAnalysis>(F); - bool Changed = runCodePreprationImpl(F, &DT, &LI, nullptr); - if (!Changed) - return PreservedAnalyses::all(); - - PreservedAnalyses PA; - PA.preserve<DominatorTreeAnalysis>(); - PA.preserve<LoopAnalysis>(); - return PA; -} - -void CodePreparation::clear() {} - -CodePreparation::~CodePreparation() { clear(); } - -void CodePreparation::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<LoopInfoWrapperPass>(); - - AU.addPreserved<LoopInfoWrapperPass>(); - AU.addPreserved<RegionInfoPass>(); - AU.addPreserved<DominatorTreeWrapperPass>(); - AU.addPreserved<DominanceFrontierWrapperPass>(); +bool polly::runCodePreparation(Function &F, DominatorTree *DT, LoopInfo *LI, + RegionInfo *RI) { + return runCodePreprationImpl(F, DT, LI, RI); } - -bool CodePreparation::runOnFunction(Function &F) { - if (skipFunction(F)) - return false; - - DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); - RegionInfo *RI = &getAnalysis<RegionInfoPass>().getRegionInfo(); - - runCodePreprationImpl(F, DT, LI, RI); - - return true; -} - -void CodePreparation::releaseMemory() { clear(); } - -void CodePreparation::print(raw_ostream &OS, const Module *) const {} - -char CodePreparation::ID = 0; -char &polly::CodePreparationID = CodePreparation::ID; - -Pass *polly::createCodePreparationPass() { return new CodePreparation(); } - -INITIALIZE_PASS_BEGIN(CodePreparation, "polly-prepare", - "Polly - Prepare code for polly", false, false) -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) -INITIALIZE_PASS_END(CodePreparation, "polly-prepare", - "Polly - Prepare code for polly", false, false) diff --git a/polly/lib/Transform/DeLICM.cpp b/polly/lib/Transform/DeLICM.cpp index 9a9768a..4deace1 100644 --- a/polly/lib/Transform/DeLICM.cpp +++ b/polly/lib/Transform/DeLICM.cpp @@ -15,17 +15,14 @@ //===----------------------------------------------------------------------===// #include "polly/DeLICM.h" -#include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "polly/ScopInfo.h" -#include "polly/ScopPass.h" #include "polly/Support/GICHelper.h" #include "polly/Support/ISLOStream.h" #include "polly/Support/ISLTools.h" #include "polly/ZoneAlgo.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/Module.h" -#include "llvm/InitializePasses.h" #include "polly/Support/PollyDebug.h" #define DEBUG_TYPE "polly-delicm" @@ -35,6 +32,10 @@ using namespace llvm; namespace { +static cl::opt<bool> PollyPrintDeLICM("polly-print-delicm", + cl::desc("Polly - Print DeLICM/DePRE"), + cl::cat(PollyCategory)); + cl::opt<int> DelicmMaxOps("polly-delicm-max-ops", cl::desc("Maximum number of isl operations to invest for " @@ -1356,7 +1357,10 @@ public: } /// Return whether at least one transformation been applied. - bool isModified() const { return NumberOfTargetsMapped > 0; } + bool isModified() const { + return NumberOfTargetsMapped > 0 || NumberOfMappedValueScalars > 0 || + NumberOfMappedPHIScalars > 0; + } }; static std::unique_ptr<DeLICMImpl> collapseToUnused(Scop &S, LoopInfo &LI) { @@ -1376,7 +1380,7 @@ static std::unique_ptr<DeLICMImpl> collapseToUnused(Scop &S, LoopInfo &LI) { return Impl; } -static std::unique_ptr<DeLICMImpl> runDeLICM(Scop &S, LoopInfo &LI) { +static std::unique_ptr<DeLICMImpl> runDeLICMImpl(Scop &S, LoopInfo &LI) { std::unique_ptr<DeLICMImpl> Impl = collapseToUnused(S, LI); Scop::ScopStatistics ScopStats = S.getStatistics(); @@ -1389,130 +1393,8 @@ static std::unique_ptr<DeLICMImpl> runDeLICM(Scop &S, LoopInfo &LI) { return Impl; } - -static PreservedAnalyses runDeLICMUsingNPM(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &U, raw_ostream *OS) { - LoopInfo &LI = SAR.LI; - std::unique_ptr<DeLICMImpl> Impl = runDeLICM(S, LI); - - if (OS) { - *OS << "Printing analysis 'Polly - DeLICM/DePRE' for region: '" - << S.getName() << "' in function '" << S.getFunction().getName() - << "':\n"; - if (Impl) { - assert(Impl->getScop() == &S); - - *OS << "DeLICM result:\n"; - Impl->print(*OS); - } - } - - if (!Impl->isModified()) - return PreservedAnalyses::all(); - - PreservedAnalyses PA; - PA.preserveSet<AllAnalysesOn<Module>>(); - PA.preserveSet<AllAnalysesOn<Function>>(); - PA.preserveSet<AllAnalysesOn<Loop>>(); - return PA; -} - -class DeLICMWrapperPass final : public ScopPass { -private: - DeLICMWrapperPass(const DeLICMWrapperPass &) = delete; - const DeLICMWrapperPass &operator=(const DeLICMWrapperPass &) = delete; - - /// The pass implementation, also holding per-scop data. - std::unique_ptr<DeLICMImpl> Impl; - -public: - static char ID; - explicit DeLICMWrapperPass() : ScopPass(ID) {} - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequiredTransitive<ScopInfoRegionPass>(); - AU.addRequired<LoopInfoWrapperPass>(); - AU.setPreservesAll(); - } - - bool runOnScop(Scop &S) override { - // Free resources for previous scop's computation, if not yet done. - releaseMemory(); - - auto &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); - Impl = runDeLICM(S, LI); - - return Impl->isModified(); - } - - void printScop(raw_ostream &OS, Scop &S) const override { - if (!Impl) - return; - assert(Impl->getScop() == &S); - - OS << "DeLICM result:\n"; - Impl->print(OS); - } - - void releaseMemory() override { Impl.reset(); } -}; - -char DeLICMWrapperPass::ID; - -/// Print result from DeLICMWrapperPass. -class DeLICMPrinterLegacyPass final : public ScopPass { -public: - static char ID; - - DeLICMPrinterLegacyPass() : DeLICMPrinterLegacyPass(outs()) {} - explicit DeLICMPrinterLegacyPass(llvm::raw_ostream &OS) - : ScopPass(ID), OS(OS) {} - - bool runOnScop(Scop &S) override { - DeLICMWrapperPass &P = getAnalysis<DeLICMWrapperPass>(); - - OS << "Printing analysis '" << P.getPassName() << "' for region: '" - << S.getRegion().getNameStr() << "' in function '" - << S.getFunction().getName() << "':\n"; - P.printScop(OS, S); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<DeLICMWrapperPass>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char DeLICMPrinterLegacyPass::ID = 0; } // anonymous namespace -Pass *polly::createDeLICMWrapperPass() { return new DeLICMWrapperPass(); } - -llvm::Pass *polly::createDeLICMPrinterLegacyPass(llvm::raw_ostream &OS) { - return new DeLICMPrinterLegacyPass(OS); -} - -llvm::PreservedAnalyses polly::DeLICMPass::run(Scop &S, - ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &U) { - return runDeLICMUsingNPM(S, SAM, SAR, U, nullptr); -} - -llvm::PreservedAnalyses DeLICMPrinterPass::run(Scop &S, - ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &U) { - return runDeLICMUsingNPM(S, SAM, SAR, U, &OS); -} - bool polly::isConflicting( isl::union_set ExistingOccupied, isl::union_set ExistingUnused, isl::union_map ExistingKnown, isl::union_map ExistingWrites, @@ -1527,15 +1409,21 @@ bool polly::isConflicting( return Knowledge::isConflicting(Existing, Proposed, OS, Indent); } -INITIALIZE_PASS_BEGIN(DeLICMWrapperPass, "polly-delicm", "Polly - DeLICM/DePRE", - false, false) -INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass) -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) -INITIALIZE_PASS_END(DeLICMWrapperPass, "polly-delicm", "Polly - DeLICM/DePRE", - false, false) - -INITIALIZE_PASS_BEGIN(DeLICMPrinterLegacyPass, "polly-print-delicm", - "Polly - Print DeLICM/DePRE", false, false) -INITIALIZE_PASS_DEPENDENCY(ScopInfoWrapperPass) -INITIALIZE_PASS_END(DeLICMPrinterLegacyPass, "polly-print-delicm", - "Polly - Print DeLICM/DePRE", false, false) +bool polly::runDeLICM(Scop &S) { + LoopInfo &LI = *S.getLI(); + std::unique_ptr<DeLICMImpl> Impl = runDeLICMImpl(S, LI); + + if (PollyPrintDeLICM) { + outs() << "Printing analysis 'Polly - DeLICM/DePRE' for region: '" + << S.getName() << "' in function '" << S.getFunction().getName() + << "':\n"; + if (Impl) { + assert(Impl->getScop() == &S); + + outs() << "DeLICM result:\n"; + Impl->print(outs()); + } + } + + return Impl->isModified(); +} diff --git a/polly/lib/Transform/DeadCodeElimination.cpp b/polly/lib/Transform/DeadCodeElimination.cpp index 5cb89fe..7cb7400 100644 --- a/polly/lib/Transform/DeadCodeElimination.cpp +++ b/polly/lib/Transform/DeadCodeElimination.cpp @@ -33,7 +33,6 @@ #include "polly/DeadCodeElimination.h" #include "polly/DependenceInfo.h" -#include "polly/LinkAllPasses.h" #include "polly/Options.h" #include "polly/ScopInfo.h" #include "llvm/Support/CommandLine.h" @@ -51,20 +50,6 @@ cl::opt<int> DCEPreciseSteps( "before the actual dead code elimination."), cl::init(-1), cl::cat(PollyCategory)); -class DeadCodeElimWrapperPass final : public ScopPass { -public: - static char ID; - explicit DeadCodeElimWrapperPass() : ScopPass(ID) {} - - /// Remove dead iterations from the schedule of @p S. - bool runOnScop(Scop &S) override; - - /// Register all analyses and transformation required. - void getAnalysisUsage(AnalysisUsage &AU) const override; -}; - -char DeadCodeElimWrapperPass::ID = 0; - /// Return the set of live iterations. /// /// The set of live iterations are all iterations that write to memory and for @@ -144,35 +129,9 @@ static bool runDeadCodeElimination(Scop &S, int PreciseSteps, return S.restrictDomains(Live); } -bool DeadCodeElimWrapperPass::runOnScop(Scop &S) { - auto &DI = getAnalysis<DependenceInfo>(); - const Dependences &Deps = DI.getDependences(Dependences::AL_Statement); - - bool Changed = runDeadCodeElimination(S, DCEPreciseSteps, Deps); - - // FIXME: We can probably avoid the recomputation of all dependences by - // updating them explicitly. - if (Changed) - DI.recomputeDependences(Dependences::AL_Statement); - - return false; -} - -void DeadCodeElimWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<DependenceInfo>(); -} - } // namespace -Pass *polly::createDeadCodeElimWrapperPass() { - return new DeadCodeElimWrapperPass(); -} - -llvm::PreservedAnalyses DeadCodeElimPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &U) { - DependenceAnalysis::Result &DA = SAM.getResult<DependenceAnalysis>(S, SAR); +bool polly::runDeadCodeElim(Scop &S, DependenceAnalysis::Result &DA) { const Dependences &Deps = DA.getDependences(Dependences::AL_Statement); bool Changed = runDeadCodeElimination(S, DCEPreciseSteps, Deps); @@ -182,19 +141,5 @@ llvm::PreservedAnalyses DeadCodeElimPass::run(Scop &S, ScopAnalysisManager &SAM, if (Changed) DA.recomputeDependences(Dependences::AL_Statement); - if (!Changed) - return PreservedAnalyses::all(); - - PreservedAnalyses PA; - PA.preserveSet<AllAnalysesOn<Module>>(); - PA.preserveSet<AllAnalysesOn<Function>>(); - PA.preserveSet<AllAnalysesOn<Loop>>(); - return PA; + return Changed; } - -INITIALIZE_PASS_BEGIN(DeadCodeElimWrapperPass, "polly-dce", - "Polly - Remove dead iterations", false, false) -INITIALIZE_PASS_DEPENDENCY(DependenceInfo) -INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass) -INITIALIZE_PASS_END(DeadCodeElimWrapperPass, "polly-dce", - "Polly - Remove dead iterations", false, false) diff --git a/polly/lib/Transform/FlattenSchedule.cpp b/polly/lib/Transform/FlattenSchedule.cpp index f514ef3..3bb3c2f 100644 --- a/polly/lib/Transform/FlattenSchedule.cpp +++ b/polly/lib/Transform/FlattenSchedule.cpp @@ -14,8 +14,8 @@ #include "polly/FlattenSchedule.h" #include "polly/FlattenAlgo.h" +#include "polly/Options.h" #include "polly/ScopInfo.h" -#include "polly/ScopPass.h" #include "polly/Support/ISLOStream.h" #include "polly/Support/ISLTools.h" #include "polly/Support/PollyDebug.h" @@ -26,6 +26,10 @@ using namespace llvm; namespace { +static cl::opt<bool> PollyPrintFlattenSchedule("polly-print-flatten-schedule", + cl::desc("A polly pass"), + cl::cat(PollyCategory)); + /// Print a schedule to @p OS. /// /// Prints the schedule for each statements on a new line. @@ -34,119 +38,45 @@ void printSchedule(raw_ostream &OS, const isl::union_map &Schedule, for (isl::map Map : Schedule.get_map_list()) OS.indent(indent) << Map << "\n"; } +} // namespace -/// Flatten the schedule stored in an polly::Scop. -class FlattenSchedule final : public ScopPass { -private: - FlattenSchedule(const FlattenSchedule &) = delete; - const FlattenSchedule &operator=(const FlattenSchedule &) = delete; - - std::shared_ptr<isl_ctx> IslCtx; - isl::union_map OldSchedule; - -public: - static char ID; - explicit FlattenSchedule() : ScopPass(ID) {} - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequiredTransitive<ScopInfoRegionPass>(); - AU.setPreservesAll(); - } - - bool runOnScop(Scop &S) override { - // Keep a reference to isl_ctx to ensure that it is not freed before we free - // OldSchedule. - IslCtx = S.getSharedIslCtx(); +void polly::runFlattenSchedulePass(Scop &S) { + // Keep a reference to isl_ctx to ensure that it is not freed before we free + // OldSchedule. + auto IslCtx = S.getSharedIslCtx(); - POLLY_DEBUG(dbgs() << "Going to flatten old schedule:\n"); - OldSchedule = S.getSchedule(); - POLLY_DEBUG(printSchedule(dbgs(), OldSchedule, 2)); + POLLY_DEBUG(dbgs() << "Going to flatten old schedule:\n"); + auto OldSchedule = S.getSchedule(); + POLLY_DEBUG(printSchedule(dbgs(), OldSchedule, 2)); - auto Domains = S.getDomains(); - auto RestrictedOldSchedule = OldSchedule.intersect_domain(Domains); - POLLY_DEBUG(dbgs() << "Old schedule with domains:\n"); - POLLY_DEBUG(printSchedule(dbgs(), RestrictedOldSchedule, 2)); + auto Domains = S.getDomains(); + auto RestrictedOldSchedule = OldSchedule.intersect_domain(Domains); + POLLY_DEBUG(dbgs() << "Old schedule with domains:\n"); + POLLY_DEBUG(printSchedule(dbgs(), RestrictedOldSchedule, 2)); - auto NewSchedule = flattenSchedule(RestrictedOldSchedule); + auto NewSchedule = flattenSchedule(RestrictedOldSchedule); - POLLY_DEBUG(dbgs() << "Flattened new schedule:\n"); - POLLY_DEBUG(printSchedule(dbgs(), NewSchedule, 2)); + POLLY_DEBUG(dbgs() << "Flattened new schedule:\n"); + POLLY_DEBUG(printSchedule(dbgs(), NewSchedule, 2)); - NewSchedule = NewSchedule.gist_domain(Domains); - POLLY_DEBUG(dbgs() << "Gisted, flattened new schedule:\n"); - POLLY_DEBUG(printSchedule(dbgs(), NewSchedule, 2)); + NewSchedule = NewSchedule.gist_domain(Domains); + POLLY_DEBUG(dbgs() << "Gisted, flattened new schedule:\n"); + POLLY_DEBUG(printSchedule(dbgs(), NewSchedule, 2)); - S.setSchedule(NewSchedule); - return false; - } + S.setSchedule(NewSchedule); - void printScop(raw_ostream &OS, Scop &S) const override { - OS << "Schedule before flattening {\n"; - printSchedule(OS, OldSchedule, 4); - OS << "}\n\n"; + if (PollyPrintFlattenSchedule) { + outs() + << "Printing analysis 'Polly - Print flattened schedule' for region: '" + << S.getRegion().getNameStr() << "' in function '" + << S.getFunction().getName() << "':\n"; - OS << "Schedule after flattening {\n"; - printSchedule(OS, S.getSchedule(), 4); - OS << "}\n"; - } + outs() << "Schedule before flattening {\n"; + printSchedule(outs(), OldSchedule, 4); + outs() << "}\n\n"; - void releaseMemory() override { - OldSchedule = {}; - IslCtx.reset(); + outs() << "Schedule after flattening {\n"; + printSchedule(outs(), S.getSchedule(), 4); + outs() << "}\n"; } -}; - -char FlattenSchedule::ID; - -/// Print result from FlattenSchedule. -class FlattenSchedulePrinterLegacyPass final : public ScopPass { -public: - static char ID; - - FlattenSchedulePrinterLegacyPass() - : FlattenSchedulePrinterLegacyPass(outs()) {} - explicit FlattenSchedulePrinterLegacyPass(llvm::raw_ostream &OS) - : ScopPass(ID), OS(OS) {} - - bool runOnScop(Scop &S) override { - FlattenSchedule &P = getAnalysis<FlattenSchedule>(); - - OS << "Printing analysis '" << P.getPassName() << "' for region: '" - << S.getRegion().getNameStr() << "' in function '" - << S.getFunction().getName() << "':\n"; - P.printScop(OS, S); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<FlattenSchedule>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char FlattenSchedulePrinterLegacyPass::ID = 0; -} // anonymous namespace - -Pass *polly::createFlattenSchedulePass() { return new FlattenSchedule(); } - -Pass *polly::createFlattenSchedulePrinterLegacyPass(llvm::raw_ostream &OS) { - return new FlattenSchedulePrinterLegacyPass(OS); } - -INITIALIZE_PASS_BEGIN(FlattenSchedule, "polly-flatten-schedule", - "Polly - Flatten schedule", false, false) -INITIALIZE_PASS_END(FlattenSchedule, "polly-flatten-schedule", - "Polly - Flatten schedule", false, false) - -INITIALIZE_PASS_BEGIN(FlattenSchedulePrinterLegacyPass, - "polly-print-flatten-schedule", - "Polly - Print flattened schedule", false, false) -INITIALIZE_PASS_DEPENDENCY(FlattenSchedule) -INITIALIZE_PASS_END(FlattenSchedulePrinterLegacyPass, - "polly-print-flatten-schedule", - "Polly - Print flattened schedule", false, false) diff --git a/polly/lib/Transform/ForwardOpTree.cpp b/polly/lib/Transform/ForwardOpTree.cpp index e9be6c9..cf0ce79 100644 --- a/polly/lib/Transform/ForwardOpTree.cpp +++ b/polly/lib/Transform/ForwardOpTree.cpp @@ -14,7 +14,6 @@ #include "polly/Options.h" #include "polly/ScopBuilder.h" #include "polly/ScopInfo.h" -#include "polly/ScopPass.h" #include "polly/Support/GICHelper.h" #include "polly/Support/ISLOStream.h" #include "polly/Support/ISLTools.h" @@ -28,7 +27,6 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Value.h" -#include "llvm/InitializePasses.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" @@ -62,6 +60,11 @@ static cl::opt<unsigned> "analysis; 0=no limit"), cl::init(1000000), cl::cat(PollyCategory), cl::Hidden); +static cl::opt<bool> + PollyPrintOptree("polly-print-optree", + cl::desc("Polly - Print forward operand tree result"), + cl::cat(PollyCategory)); + STATISTIC(KnownAnalyzed, "Number of successfully analyzed SCoPs"); STATISTIC(KnownOutOfQuota, "Analyses aborted because max_operations was reached"); @@ -1030,8 +1033,8 @@ public: bool isModified() const { return Modified; } }; -static std::unique_ptr<ForwardOpTreeImpl> runForwardOpTree(Scop &S, - LoopInfo &LI) { +static std::unique_ptr<ForwardOpTreeImpl> runForwardOpTreeImpl(Scop &S, + LoopInfo &LI) { std::unique_ptr<ForwardOpTreeImpl> Impl; { IslMaxOperationsGuard MaxOpGuard(S.getIslCtx().get(), MaxOps, false); @@ -1066,148 +1069,22 @@ static std::unique_ptr<ForwardOpTreeImpl> runForwardOpTree(Scop &S, return Impl; } +} // namespace -static PreservedAnalyses -runForwardOpTreeUsingNPM(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, SPMUpdater &U, - raw_ostream *OS) { - LoopInfo &LI = SAR.LI; - - std::unique_ptr<ForwardOpTreeImpl> Impl = runForwardOpTree(S, LI); - if (OS) { - *OS << "Printing analysis 'Polly - Forward operand tree' for region: '" - << S.getName() << "' in function '" << S.getFunction().getName() - << "':\n"; +bool polly::runForwardOpTree(Scop &S) { + LoopInfo &LI = *S.getLI(); + + std::unique_ptr<ForwardOpTreeImpl> Impl = runForwardOpTreeImpl(S, LI); + if (PollyPrintOptree) { + outs() << "Printing analysis 'Polly - Forward operand tree' for region: '" + << S.getName() << "' in function '" << S.getFunction().getName() + << "':\n"; if (Impl) { assert(Impl->getScop() == &S); - Impl->print(*OS); + Impl->print(outs()); } } - if (!Impl->isModified()) - return PreservedAnalyses::all(); - - PreservedAnalyses PA; - PA.preserveSet<AllAnalysesOn<Module>>(); - PA.preserveSet<AllAnalysesOn<Function>>(); - PA.preserveSet<AllAnalysesOn<Loop>>(); - return PA; -} - -/// Pass that redirects scalar reads to array elements that are known to contain -/// the same value. -/// -/// This reduces the number of scalar accesses and therefore potentially -/// increases the freedom of the scheduler. In the ideal case, all reads of a -/// scalar definition are redirected (We currently do not care about removing -/// the write in this case). This is also useful for the main DeLICM pass as -/// there are less scalars to be mapped. -class ForwardOpTreeWrapperPass final : public ScopPass { -private: - /// The pass implementation, also holding per-scop data. - std::unique_ptr<ForwardOpTreeImpl> Impl; - -public: - static char ID; - - explicit ForwardOpTreeWrapperPass() : ScopPass(ID) {} - ForwardOpTreeWrapperPass(const ForwardOpTreeWrapperPass &) = delete; - ForwardOpTreeWrapperPass & - operator=(const ForwardOpTreeWrapperPass &) = delete; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequiredTransitive<ScopInfoRegionPass>(); - AU.addRequired<LoopInfoWrapperPass>(); - AU.setPreservesAll(); - } - - bool runOnScop(Scop &S) override { - // Free resources for previous SCoP's computation, if not yet done. - releaseMemory(); - - LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); - - Impl = runForwardOpTree(S, LI); - - return false; - } - - void printScop(raw_ostream &OS, Scop &S) const override { - if (!Impl) - return; - - assert(Impl->getScop() == &S); - Impl->print(OS); - } - - void releaseMemory() override { Impl.reset(); } -}; // class ForwardOpTree - -char ForwardOpTreeWrapperPass::ID; - -/// Print result from ForwardOpTreeWrapperPass. -class ForwardOpTreePrinterLegacyPass final : public ScopPass { -public: - static char ID; - - ForwardOpTreePrinterLegacyPass() : ForwardOpTreePrinterLegacyPass(outs()) {} - explicit ForwardOpTreePrinterLegacyPass(llvm::raw_ostream &OS) - : ScopPass(ID), OS(OS) {} - - bool runOnScop(Scop &S) override { - ForwardOpTreeWrapperPass &P = getAnalysis<ForwardOpTreeWrapperPass>(); - - OS << "Printing analysis '" << P.getPassName() << "' for region: '" - << S.getRegion().getNameStr() << "' in function '" - << S.getFunction().getName() << "':\n"; - P.printScop(OS, S); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<ForwardOpTreeWrapperPass>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char ForwardOpTreePrinterLegacyPass::ID = 0; -} // namespace - -Pass *polly::createForwardOpTreeWrapperPass() { - return new ForwardOpTreeWrapperPass(); -} - -Pass *polly::createForwardOpTreePrinterLegacyPass(llvm::raw_ostream &OS) { - return new ForwardOpTreePrinterLegacyPass(OS); -} - -llvm::PreservedAnalyses ForwardOpTreePass::run(Scop &S, - ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &U) { - return runForwardOpTreeUsingNPM(S, SAM, SAR, U, nullptr); + return Impl->isModified(); } - -llvm::PreservedAnalyses -ForwardOpTreePrinterPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, SPMUpdater &U) { - return runForwardOpTreeUsingNPM(S, SAM, SAR, U, &OS); -} - -INITIALIZE_PASS_BEGIN(ForwardOpTreeWrapperPass, "polly-optree", - "Polly - Forward operand tree", false, false) -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) -INITIALIZE_PASS_END(ForwardOpTreeWrapperPass, "polly-optree", - "Polly - Forward operand tree", false, false) - -INITIALIZE_PASS_BEGIN(ForwardOpTreePrinterLegacyPass, "polly-print-optree", - "Polly - Print forward operand tree result", false, false) -INITIALIZE_PASS_DEPENDENCY(ForwardOpTreeWrapperPass) -INITIALIZE_PASS_END(ForwardOpTreePrinterLegacyPass, "polly-print-optree", - "Polly - Print forward operand tree result", false, false) diff --git a/polly/lib/Transform/MatmulOptimizer.cpp b/polly/lib/Transform/MatmulOptimizer.cpp index 01d431a..7a6b3d2 100644 --- a/polly/lib/Transform/MatmulOptimizer.cpp +++ b/polly/lib/Transform/MatmulOptimizer.cpp @@ -11,7 +11,6 @@ #include "polly/Options.h" #include "polly/ScheduleTreeTransform.h" #include "polly/ScopInfo.h" -#include "polly/ScopPass.h" #include "polly/Simplify.h" #include "polly/Support/GICHelper.h" #include "polly/Support/ISLTools.h" diff --git a/polly/lib/Transform/MaximalStaticExpansion.cpp b/polly/lib/Transform/MaximalStaticExpansion.cpp index 0719840..514a21f 100644 --- a/polly/lib/Transform/MaximalStaticExpansion.cpp +++ b/polly/lib/Transform/MaximalStaticExpansion.cpp @@ -13,14 +13,12 @@ #include "polly/MaximalStaticExpansion.h" #include "polly/DependenceInfo.h" -#include "polly/LinkAllPasses.h" +#include "polly/Options.h" #include "polly/ScopInfo.h" -#include "polly/ScopPass.h" #include "polly/Support/ISLTools.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" -#include "llvm/InitializePasses.h" #include "isl/isl-noexceptions.h" #include "isl/union_map.h" #include <cassert> @@ -35,28 +33,10 @@ using namespace polly; namespace { -class MaximalStaticExpanderWrapperPass final : public ScopPass { -public: - static char ID; - - explicit MaximalStaticExpanderWrapperPass() : ScopPass(ID) {} - - ~MaximalStaticExpanderWrapperPass() override = default; - - /// Expand the accesses of the SCoP. - /// - /// @param S The SCoP that must be expanded. - bool runOnScop(Scop &S) override; - - /// Print the SCoP. - /// - /// @param OS The stream where to print. - /// @param S The SCop that must be printed. - void printScop(raw_ostream &OS, Scop &S) const override; - - /// Register all analyses and transformations required. - void getAnalysisUsage(AnalysisUsage &AU) const override; -}; +static cl::opt<bool> + PollyPrintMSE("polly-print-mse", + cl::desc("Polly - Print Maximal static expansion of SCoP"), + cl::cat(PollyCategory)); #ifndef NDEBUG /// Whether a dimension of a set is bounded (lower and upper) by a constant, @@ -458,8 +438,8 @@ public: }; static std::unique_ptr<MaximalStaticExpansionImpl> -runMaximalStaticExpansion(Scop &S, OptimizationRemarkEmitter &ORE, - const Dependences &D) { +runMaximalStaticExpansionImpl(Scop &S, OptimizationRemarkEmitter &ORE, + const Dependences &D) { auto Dependences = D.getDependences(Dependences::TYPE_RAW); std::unique_ptr<MaximalStaticExpansionImpl> Impl = @@ -468,85 +448,26 @@ runMaximalStaticExpansion(Scop &S, OptimizationRemarkEmitter &ORE, Impl->expand(); return Impl; } +} // namespace -static PreservedAnalyses runMSEUsingNPM(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - raw_ostream *OS) { +void polly::runMaximalStaticExpansion(Scop &S, DependenceAnalysis::Result &DI) { OptimizationRemarkEmitter ORE(&S.getFunction()); - auto &DI = SAM.getResult<DependenceAnalysis>(S, SAR); auto &D = DI.getDependences(Dependences::AL_Reference); std::unique_ptr<MaximalStaticExpansionImpl> Impl = - runMaximalStaticExpansion(S, ORE, D); + runMaximalStaticExpansionImpl(S, ORE, D); - if (OS) { - *OS << "Printing analysis 'Polly - Maximal static expansion of SCoP' for " + if (PollyPrintMSE) { + outs() + << "Printing analysis 'Polly - Maximal static expansion of SCoP' for " "region: '" << S.getName() << "' in function '" << S.getFunction().getName() << "':\n"; if (Impl) { - *OS << "MSE result:\n"; - Impl->print(*OS); + outs() << "MSE result:\n"; + Impl->print(llvm::outs()); } } - - return PreservedAnalyses::all(); -} - -} // namespace - -PreservedAnalyses -MaximalStaticExpansionPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &) { - return runMSEUsingNPM(S, SAM, SAR, nullptr); -} - -PreservedAnalyses -MaximalStaticExpansionPrinterPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &) { - return runMSEUsingNPM(S, SAM, SAR, &OS); -} - -char MaximalStaticExpanderWrapperPass::ID = 0; - -bool MaximalStaticExpanderWrapperPass::runOnScop(Scop &S) { - // Get the ORE from OptimizationRemarkEmitterWrapperPass. - OptimizationRemarkEmitter *ORE = - &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); - - // Get the RAW Dependences. - auto &DI = getAnalysis<DependenceInfo>(); - auto &D = DI.getDependences(Dependences::AL_Reference); - - std::unique_ptr<MaximalStaticExpansionImpl> Impl = - runMaximalStaticExpansion(S, *ORE, D); - - return false; -} - -void MaximalStaticExpanderWrapperPass::printScop(raw_ostream &OS, - Scop &S) const { - S.print(OS, false); -} - -void MaximalStaticExpanderWrapperPass::getAnalysisUsage( - AnalysisUsage &AU) const { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<DependenceInfo>(); - AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); -} - -Pass *polly::createMaximalStaticExpansionPass() { - return new MaximalStaticExpanderWrapperPass(); } - -INITIALIZE_PASS_BEGIN(MaximalStaticExpanderWrapperPass, "polly-mse", - "Polly - Maximal static expansion of SCoP", false, false); -INITIALIZE_PASS_DEPENDENCY(DependenceInfo); -INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass); -INITIALIZE_PASS_END(MaximalStaticExpanderWrapperPass, "polly-mse", - "Polly - Maximal static expansion of SCoP", false, false) diff --git a/polly/lib/Transform/ScheduleOptimizer.cpp b/polly/lib/Transform/ScheduleOptimizer.cpp index f01d3de..b9b9abb 100644 --- a/polly/lib/Transform/ScheduleOptimizer.cpp +++ b/polly/lib/Transform/ScheduleOptimizer.cpp @@ -52,12 +52,12 @@ #include "polly/MatmulOptimizer.h" #include "polly/Options.h" #include "polly/ScheduleTreeTransform.h" +#include "polly/ScopInfo.h" #include "polly/Support/ISLOStream.h" #include "polly/Support/ISLTools.h" #include "llvm/ADT/Sequence.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" -#include "llvm/InitializePasses.h" #include "llvm/Support/CommandLine.h" #include "isl/options.h" @@ -198,6 +198,10 @@ static cl::opt<bool> OptimizedScops( "transformations is applied on the schedule tree"), cl::cat(PollyCategory)); +static cl::opt<bool> PollyPrintOptIsl("polly-print-opt-isl", + cl::desc("A polly pass"), + cl::cat(PollyCategory)); + STATISTIC(ScopsProcessed, "Number of scops processed"); STATISTIC(ScopsRescheduled, "Number of scops rescheduled"); STATISTIC(ScopsOptimized, "Number of scops optimized"); @@ -638,34 +642,6 @@ bool ScheduleTreeOptimizer::isProfitableSchedule(Scop &S, return changed; } -class IslScheduleOptimizerWrapperPass final : public ScopPass { -public: - static char ID; - - explicit IslScheduleOptimizerWrapperPass() : ScopPass(ID) {} - - /// Optimize the schedule of the SCoP @p S. - bool runOnScop(Scop &S) override; - - /// Print the new schedule for the SCoP @p S. - void printScop(raw_ostream &OS, Scop &S) const override; - - /// Register all analyses and transformation required. - void getAnalysisUsage(AnalysisUsage &AU) const override; - - /// Release the internal memory. - void releaseMemory() override { - LastSchedule = {}; - IslCtx.reset(); - } - -private: - std::shared_ptr<isl_ctx> IslCtx; - isl::schedule LastSchedule; -}; - -char IslScheduleOptimizerWrapperPass::ID = 0; - #ifndef NDEBUG static void printSchedule(llvm::raw_ostream &OS, const isl::schedule &Schedule, StringRef Desc) { @@ -733,7 +709,7 @@ static void walkScheduleTreeForStatistics(isl::schedule Schedule, int Version) { &Version); } -static void runIslScheduleOptimizer( +static void runIslScheduleOptimizerImpl( Scop &S, function_ref<const Dependences &(Dependences::AnalysisLevel)> GetDeps, TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE, @@ -966,30 +942,6 @@ static void runIslScheduleOptimizer( errs() << S; } -bool IslScheduleOptimizerWrapperPass::runOnScop(Scop &S) { - releaseMemory(); - - Function &F = S.getFunction(); - IslCtx = S.getSharedIslCtx(); - - auto getDependences = - [this](Dependences::AnalysisLevel) -> const Dependences & { - return getAnalysis<DependenceInfo>().getDependences( - Dependences::AL_Statement); - }; - OptimizationRemarkEmitter &ORE = - getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE(); - TargetTransformInfo *TTI = - &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); - - bool DepsChanged = false; - runIslScheduleOptimizer(S, getDependences, TTI, &ORE, LastSchedule, - DepsChanged); - if (DepsChanged) - getAnalysis<DependenceInfo>().abandonDependences(); - return false; -} - static void runScheduleOptimizerPrinter(raw_ostream &OS, isl::schedule LastSchedule) { isl_printer *p; @@ -1013,120 +965,25 @@ static void runScheduleOptimizerPrinter(raw_ostream &OS, free(ScheduleStr); } -void IslScheduleOptimizerWrapperPass::printScop(raw_ostream &OS, Scop &) const { - runScheduleOptimizerPrinter(OS, LastSchedule); -} - -void IslScheduleOptimizerWrapperPass::getAnalysisUsage( - AnalysisUsage &AU) const { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<DependenceInfo>(); - AU.addRequired<TargetTransformInfoWrapperPass>(); - AU.addRequired<OptimizationRemarkEmitterWrapperPass>(); - - AU.addPreserved<DependenceInfo>(); - AU.addPreserved<OptimizationRemarkEmitterWrapperPass>(); -} - } // namespace -Pass *polly::createIslScheduleOptimizerWrapperPass() { - return new IslScheduleOptimizerWrapperPass(); -} - -INITIALIZE_PASS_BEGIN(IslScheduleOptimizerWrapperPass, "polly-opt-isl", - "Polly - Optimize schedule of SCoP", false, false); -INITIALIZE_PASS_DEPENDENCY(DependenceInfo); -INITIALIZE_PASS_DEPENDENCY(ScopInfoRegionPass); -INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass); -INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass); -INITIALIZE_PASS_END(IslScheduleOptimizerWrapperPass, "polly-opt-isl", - "Polly - Optimize schedule of SCoP", false, false) - -static llvm::PreservedAnalyses -runIslScheduleOptimizerUsingNPM(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, SPMUpdater &U, - raw_ostream *OS) { - DependenceAnalysis::Result &Deps = SAM.getResult<DependenceAnalysis>(S, SAR); +void polly::runIslScheduleOptimizer(Scop &S, TargetTransformInfo *TTI, + DependenceAnalysis::Result &Deps) { auto GetDeps = [&Deps](Dependences::AnalysisLevel) -> const Dependences & { return Deps.getDependences(Dependences::AL_Statement); }; OptimizationRemarkEmitter ORE(&S.getFunction()); - TargetTransformInfo *TTI = &SAR.TTI; isl::schedule LastSchedule; bool DepsChanged = false; - runIslScheduleOptimizer(S, GetDeps, TTI, &ORE, LastSchedule, DepsChanged); + runIslScheduleOptimizerImpl(S, GetDeps, TTI, &ORE, LastSchedule, DepsChanged); if (DepsChanged) Deps.abandonDependences(); - if (OS) { - *OS << "Printing analysis 'Polly - Optimize schedule of SCoP' for region: '" + if (PollyPrintOptIsl) { + outs() + << "Printing analysis 'Polly - Optimize schedule of SCoP' for region: '" << S.getName() << "' in function '" << S.getFunction().getName() << "':\n"; - runScheduleOptimizerPrinter(*OS, LastSchedule); + runScheduleOptimizerPrinter(outs(), LastSchedule); } - return PreservedAnalyses::all(); -} - -llvm::PreservedAnalyses -IslScheduleOptimizerPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, SPMUpdater &U) { - return runIslScheduleOptimizerUsingNPM(S, SAM, SAR, U, nullptr); } - -llvm::PreservedAnalyses -IslScheduleOptimizerPrinterPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &U) { - return runIslScheduleOptimizerUsingNPM(S, SAM, SAR, U, &OS); -} - -//===----------------------------------------------------------------------===// - -namespace { -/// Print result from IslScheduleOptimizerWrapperPass. -class IslScheduleOptimizerPrinterLegacyPass final : public ScopPass { -public: - static char ID; - - IslScheduleOptimizerPrinterLegacyPass() - : IslScheduleOptimizerPrinterLegacyPass(outs()) {} - explicit IslScheduleOptimizerPrinterLegacyPass(llvm::raw_ostream &OS) - : ScopPass(ID), OS(OS) {} - - bool runOnScop(Scop &S) override { - IslScheduleOptimizerWrapperPass &P = - getAnalysis<IslScheduleOptimizerWrapperPass>(); - - OS << "Printing analysis '" << P.getPassName() << "' for region: '" - << S.getRegion().getNameStr() << "' in function '" - << S.getFunction().getName() << "':\n"; - P.printScop(OS, S); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<IslScheduleOptimizerWrapperPass>(); - AU.setPreservesAll(); - } - -private: - llvm::raw_ostream &OS; -}; - -char IslScheduleOptimizerPrinterLegacyPass::ID = 0; -} // namespace - -Pass *polly::createIslScheduleOptimizerPrinterLegacyPass(raw_ostream &OS) { - return new IslScheduleOptimizerPrinterLegacyPass(OS); -} - -INITIALIZE_PASS_BEGIN(IslScheduleOptimizerPrinterLegacyPass, - "polly-print-opt-isl", - "Polly - Print optimizer schedule of SCoP", false, false); -INITIALIZE_PASS_DEPENDENCY(IslScheduleOptimizerWrapperPass) -INITIALIZE_PASS_END(IslScheduleOptimizerPrinterLegacyPass, - "polly-print-opt-isl", - "Polly - Print optimizer schedule of SCoP", false, false) diff --git a/polly/lib/Transform/ScopInliner.cpp b/polly/lib/Transform/ScopInliner.cpp index c04ba34..794ba98 100644 --- a/polly/lib/Transform/ScopInliner.cpp +++ b/polly/lib/Transform/ScopInliner.cpp @@ -21,7 +21,6 @@ #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/RegionInfo.h" #include "llvm/IR/Dominators.h" -#include "llvm/IR/PassManager.h" #include "llvm/Passes/PassBuilder.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" @@ -95,53 +94,7 @@ template <typename SCC_t> bool runScopInlinerImpl(Function *F, SCC_t &SCC) { return Changed; } - -class ScopInlinerWrapperPass final : public CallGraphSCCPass { - using llvm::Pass::doInitialization; - -public: - static char ID; - - ScopInlinerWrapperPass() : CallGraphSCCPass(ID) {} - - bool doInitialization(CallGraph &CG) override { - if (!polly::PollyAllowFullFunction) { - report_fatal_error( - "Aborting from ScopInliner because it only makes sense to run with " - "-polly-allow-full-function. " - "The heurtistic for ScopInliner checks that the full function is a " - "Scop, which happens if and only if polly-allow-full-function is " - " enabled. " - " If not, the entry block is not included in the Scop"); - } - return true; - } - - bool runOnSCC(CallGraphSCC &SCC) override { - Function *F = (*SCC.begin())->getFunction(); - return runScopInlinerImpl(F, SCC); - }; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - CallGraphSCCPass::getAnalysisUsage(AU); - } -}; } // namespace -char ScopInlinerWrapperPass::ID; - -Pass *polly::createScopInlinerWrapperPass() { - ScopInlinerWrapperPass *pass = new ScopInlinerWrapperPass(); - return pass; -} - -INITIALIZE_PASS_BEGIN( - ScopInlinerWrapperPass, "polly-scop-inliner", - "inline functions based on how much of the function is a scop.", false, - false) -INITIALIZE_PASS_END( - ScopInlinerWrapperPass, "polly-scop-inliner", - "inline functions based on how much of the function is a scop.", false, - false) polly::ScopInlinerPass::ScopInlinerPass() { if (!polly::PollyAllowFullFunction) { diff --git a/polly/lib/Transform/Simplify.cpp b/polly/lib/Transform/Simplify.cpp index 75e91cd..df88b5e 100644 --- a/polly/lib/Transform/Simplify.cpp +++ b/polly/lib/Transform/Simplify.cpp @@ -11,14 +11,13 @@ //===----------------------------------------------------------------------===// #include "polly/Simplify.h" +#include "polly/Options.h" #include "polly/ScopInfo.h" -#include "polly/ScopPass.h" #include "polly/Support/GICHelper.h" #include "polly/Support/ISLOStream.h" #include "polly/Support/ISLTools.h" #include "polly/Support/VirtualInstruction.h" #include "llvm/ADT/Statistic.h" -#include "llvm/InitializePasses.h" #include "llvm/Support/Debug.h" #include <optional> @@ -30,6 +29,11 @@ using namespace polly; namespace { +static cl::opt<bool> + PollyPrintSimplify("polly-print-simplify", + cl::desc("Polly - Print Simplify actions"), + cl::cat(PollyCategory)); + #define TWO_STATISTICS(VARNAME, DESC) \ static llvm::Statistic VARNAME[2] = { \ {DEBUG_TYPE, #VARNAME "0", DESC " (first)"}, \ @@ -756,75 +760,8 @@ void SimplifyImpl::printScop(raw_ostream &OS, Scop &S) const { printAccesses(OS); } -class SimplifyWrapperPass final : public ScopPass { -public: - static char ID; - int CallNo; - std::optional<SimplifyImpl> Impl; - - explicit SimplifyWrapperPass(int CallNo = 0) : ScopPass(ID), CallNo(CallNo) {} - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequiredTransitive<ScopInfoRegionPass>(); - AU.addRequired<LoopInfoWrapperPass>(); - AU.setPreservesAll(); - } - - bool runOnScop(Scop &S) override { - LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); - - Impl.emplace(CallNo); - Impl->run(S, LI); - - return false; - } - - void printScop(raw_ostream &OS, Scop &S) const override { - if (Impl) - Impl->printScop(OS, S); - } - - void releaseMemory() override { Impl.reset(); } -}; - -char SimplifyWrapperPass::ID; - -static llvm::PreservedAnalyses -runSimplifyUsingNPM(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, SPMUpdater &U, int CallNo, - raw_ostream *OS) { - SimplifyImpl Impl(CallNo); - Impl.run(S, &SAR.LI); - if (OS) { - *OS << "Printing analysis 'Polly - Simplify' for region: '" << S.getName() - << "' in function '" << S.getFunction().getName() << "':\n"; - Impl.printScop(*OS, S); - } - - if (!Impl.isModified()) - return llvm::PreservedAnalyses::all(); - - PreservedAnalyses PA; - PA.preserveSet<AllAnalysesOn<Module>>(); - PA.preserveSet<AllAnalysesOn<Function>>(); - PA.preserveSet<AllAnalysesOn<Loop>>(); - return PA; -} - } // anonymous namespace -llvm::PreservedAnalyses SimplifyPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, - SPMUpdater &U) { - return runSimplifyUsingNPM(S, SAM, SAR, U, CallNo, nullptr); -} - -llvm::PreservedAnalyses -SimplifyPrinterPass::run(Scop &S, ScopAnalysisManager &SAM, - ScopStandardAnalysisResults &SAR, SPMUpdater &U) { - return runSimplifyUsingNPM(S, SAM, SAR, U, CallNo, &OS); -} - SmallVector<MemoryAccess *, 32> polly::getAccessesInOrder(ScopStmt &Stmt) { SmallVector<MemoryAccess *, 32> Accesses; @@ -843,58 +780,15 @@ SmallVector<MemoryAccess *, 32> polly::getAccessesInOrder(ScopStmt &Stmt) { return Accesses; } -Pass *polly::createSimplifyWrapperPass(int CallNo) { - return new SimplifyWrapperPass(CallNo); -} - -INITIALIZE_PASS_BEGIN(SimplifyWrapperPass, "polly-simplify", "Polly - Simplify", - false, false) -INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) -INITIALIZE_PASS_END(SimplifyWrapperPass, "polly-simplify", "Polly - Simplify", - false, false) - -//===----------------------------------------------------------------------===// - -namespace { -/// Print result from SimplifyWrapperPass. -class SimplifyPrinterLegacyPass final : public ScopPass { -public: - static char ID; - - SimplifyPrinterLegacyPass() : SimplifyPrinterLegacyPass(outs()) {} - explicit SimplifyPrinterLegacyPass(llvm::raw_ostream &OS) - : ScopPass(ID), OS(OS) {} - - bool runOnScop(Scop &S) override { - SimplifyWrapperPass &P = getAnalysis<SimplifyWrapperPass>(); - - OS << "Printing analysis '" << P.getPassName() << "' for region: '" - << S.getRegion().getNameStr() << "' in function '" - << S.getFunction().getName() << "':\n"; - P.printScop(OS, S); - - return false; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - ScopPass::getAnalysisUsage(AU); - AU.addRequired<SimplifyWrapperPass>(); - AU.setPreservesAll(); +bool polly::runSimplify(Scop &S, int CallNo) { + SimplifyImpl Impl(CallNo); + Impl.run(S, S.getLI()); + if (PollyPrintSimplify) { + outs() << "Printing analysis 'Polly - Simplify' for region: '" + << S.getName() << "' in function '" << S.getFunction().getName() + << "':\n"; + Impl.printScop(outs(), S); } -private: - llvm::raw_ostream &OS; -}; - -char SimplifyPrinterLegacyPass::ID = 0; -} // namespace - -Pass *polly::createSimplifyPrinterLegacyPass(raw_ostream &OS) { - return new SimplifyPrinterLegacyPass(OS); + return Impl.isModified(); } - -INITIALIZE_PASS_BEGIN(SimplifyPrinterLegacyPass, "polly-print-simplify", - "Polly - Print Simplify actions", false, false) -INITIALIZE_PASS_DEPENDENCY(SimplifyWrapperPass) -INITIALIZE_PASS_END(SimplifyPrinterLegacyPass, "polly-print-simplify", - "Polly - Print Simplify actions", false, false) |
