diff options
Diffstat (limited to 'polly/lib/Transform')
| -rw-r--r-- | polly/lib/Transform/Canonicalization.cpp | 65 | ||||
| -rw-r--r-- | polly/lib/Transform/CodePreparation.cpp | 91 | ||||
| -rw-r--r-- | polly/lib/Transform/DeLICM.cpp | 166 | ||||
| -rw-r--r-- | polly/lib/Transform/DeadCodeElimination.cpp | 59 | ||||
| -rw-r--r-- | polly/lib/Transform/FlattenSchedule.cpp | 140 | ||||
| -rw-r--r-- | polly/lib/Transform/ForwardOpTree.cpp | 159 | ||||
| -rw-r--r-- | polly/lib/Transform/MatmulOptimizer.cpp | 1 | ||||
| -rw-r--r-- | polly/lib/Transform/MaximalStaticExpansion.cpp | 109 | ||||
| -rw-r--r-- | polly/lib/Transform/ScheduleOptimizer.cpp | 238 | ||||
| -rw-r--r-- | polly/lib/Transform/ScheduleTreeTransform.cpp | 5 | ||||
| -rw-r--r-- | polly/lib/Transform/ScopInliner.cpp | 47 | ||||
| -rw-r--r-- | polly/lib/Transform/Simplify.cpp | 136 |
12 files changed, 193 insertions, 1023 deletions
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 7c8579eb..3e76dbd 100644 --- a/polly/lib/Transform/CodePreparation.cpp +++ b/polly/lib/Transform/CodePreparation.cpp @@ -16,49 +16,17 @@ //===----------------------------------------------------------------------===// #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; -namespace { - -/// Prepare the IR for the scop detection. -/// -class CodePreparation final : public FunctionPass { - CodePreparation(const CodePreparation &) = delete; - const CodePreparation &operator=(const CodePreparation &) = delete; - - LoopInfo *LI; - ScalarEvolution *SE; - - 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) { - +static bool runCodePreprationImpl(Function &F, DominatorTree *DT, LoopInfo *LI, + RegionInfo *RI) { // Find first non-alloca instruction. Every basic block has a non-alloca // instruction, as every well formed basic block has a terminator. auto &EntryBlock = F.getEntryBlock(); @@ -66,55 +34,18 @@ PreservedAnalyses CodePreparationPass::run(Function &F, while (isa<AllocaInst>(I)) ++I; - auto &DT = FAM.getResult<DominatorTreeAnalysis>(F); - auto &LI = FAM.getResult<LoopAnalysis>(F); - - // splitBlock updates DT, LI and RI. - splitEntryBlockForAlloca(&EntryBlock, &DT, &LI, nullptr); - - 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.addRequired<ScalarEvolutionWrapperPass>(); - - AU.addPreserved<LoopInfoWrapperPass>(); - AU.addPreserved<RegionInfoPass>(); - AU.addPreserved<DominatorTreeWrapperPass>(); - AU.addPreserved<DominanceFrontierWrapperPass>(); -} - -bool CodePreparation::runOnFunction(Function &F) { - if (skipFunction(F)) + // Abort if not necessary to split + if (I->isTerminator() && isa<BranchInst>(I) && + cast<BranchInst>(I)->isUnconditional()) return false; - LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); - SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); - - splitEntryBlockForAlloca(&F.getEntryBlock(), this); + // splitBlock updates DT, LI and RI. + splitEntryBlockForAlloca(&EntryBlock, 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) +bool polly::runCodePreparation(Function &F, DominatorTree *DT, LoopInfo *LI, + RegionInfo *RI) { + return runCodePreprationImpl(F, DT, LI, RI); +} 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 070700a..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"); @@ -237,6 +241,7 @@ struct OptimizerAdditionalInfoTy { bool Postopts; bool Prevect; bool &DepsChanged; + IslMaxOperationsGuard &MaxOpGuard; }; class ScheduleTreeOptimizer final { @@ -381,6 +386,8 @@ private: isl::schedule_node ScheduleTreeOptimizer::isolateFullPartialTiles(isl::schedule_node Node, int VectorWidth) { + if (Node.is_null()) + return {}; assert(isl_schedule_node_get_type(Node.get()) == isl_schedule_node_band); Node = Node.child(0).child(0); isl::union_map SchedRelUMap = Node.get_prefix_schedule_relation(); @@ -391,6 +398,8 @@ ScheduleTreeOptimizer::isolateFullPartialTiles(isl::schedule_node Node, isl::union_set IsolateOption = getIsolateOptions(IsolateDomain, 1); Node = Node.parent().parent(); isl::union_set Options = IsolateOption.unite(AtomicOption); + if (Node.is_null()) + return {}; isl::schedule_node_band Result = Node.as<isl::schedule_node_band>().set_ast_build_options(Options); return Result; @@ -411,9 +420,13 @@ struct InsertSimdMarkers final : ScheduleNodeRewriter<InsertSimdMarkers> { isl::schedule_node ScheduleTreeOptimizer::prevectSchedBand( isl::schedule_node Node, unsigned DimToVectorize, int VectorWidth) { + if (Node.is_null()) + return {}; assert(isl_schedule_node_get_type(Node.get()) == isl_schedule_node_band); auto Space = isl::manage(isl_schedule_node_band_get_space(Node.get())); + if (Space.is_null()) + return {}; unsigned ScheduleDimensions = unsignedFromIslSize(Space.dim(isl::dim::set)); assert(DimToVectorize < ScheduleDimensions); @@ -439,12 +452,15 @@ isl::schedule_node ScheduleTreeOptimizer::prevectSchedBand( // Sink the inner loop into the smallest possible statements to make them // represent a single vector instruction if possible. Node = isl::manage(isl_schedule_node_band_sink(Node.release())); + if (Node.is_null()) + return {}; // Add SIMD markers to those vector statements. InsertSimdMarkers SimdMarkerInserter; Node = SimdMarkerInserter.visit(Node); - PrevectOpts++; + if (!Node.is_null()) + PrevectOpts++; return Node.parent(); } @@ -535,6 +551,8 @@ ScheduleTreeOptimizer::applyTileBandOpt(isl::schedule_node Node) { isl::schedule_node ScheduleTreeOptimizer::applyPrevectBandOpt(isl::schedule_node Node) { auto Space = isl::manage(isl_schedule_node_band_get_space(Node.get())); + if (Space.is_null()) + return {}; int Dims = unsignedFromIslSize(Space.dim(isl::dim::set)); for (int i = Dims - 1; i >= 0; i--) @@ -572,9 +590,14 @@ ScheduleTreeOptimizer::optimizeBand(__isl_take isl_schedule_node *NodeArg, Node = applyTileBandOpt(Node); if (OAI->Prevect) { + IslQuotaScope MaxScope = OAI->MaxOpGuard.enter(); + // FIXME: Prevectorization requirements are different from those checked by // isTileableBandNode. Node = applyPrevectBandOpt(Node); + + if (OAI->MaxOpGuard.hasQuotaExceeded() || Node.is_null()) + return (isl::schedule_node()).release(); } return Node.release(); @@ -619,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) { @@ -714,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, @@ -771,6 +766,10 @@ static void runIslScheduleOptimizer( return; } + isl_ctx *Ctx = S.getIslCtx().get(); + IslMaxOperationsGuard MaxOpGuard(Ctx, ScheduleComputeOut, + /*AutoEnter=*/false); + // Apply ISL's algorithm only if not overridden by the user. Note that // post-rescheduling optimizations (tiling, pattern-based, prevectorization) // rely on the coincidence/permutable annotations on schedule tree bands that @@ -853,8 +852,6 @@ static void runIslScheduleOptimizer( IslOuterCoincidence = 0; } - isl_ctx *Ctx = S.getIslCtx().get(); - isl_options_set_schedule_outer_coincidence(Ctx, IslOuterCoincidence); isl_options_set_schedule_maximize_band_depth(Ctx, IslMaximizeBands); isl_options_set_schedule_max_constant_term(Ctx, MaxConstantTerm); @@ -870,28 +867,20 @@ static void runIslScheduleOptimizer( SC = SC.set_coincidence(Validity); { - IslMaxOperationsGuard MaxOpGuard(Ctx, ScheduleComputeOut); + IslQuotaScope MaxOpScope = MaxOpGuard.enter(); Schedule = SC.compute_schedule(); - - if (MaxOpGuard.hasQuotaExceeded()) - POLLY_DEBUG( - dbgs() << "Schedule optimizer calculation exceeds ISL quota\n"); } isl_options_set_on_error(Ctx, OnErrorStatus); - ScopsRescheduled++; + if (!Schedule.is_null()) + ScopsRescheduled++; POLLY_DEBUG(printSchedule(dbgs(), Schedule, "After rescheduling")); } walkScheduleTreeForStatistics(Schedule, 1); - // In cases the scheduler is not able to optimize the code, we just do not - // touch the schedule. - if (Schedule.is_null()) - return; - - if (GreedyFusion) { + if (GreedyFusion && !Schedule.is_null()) { isl::union_map Validity = D.getDependences( Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW); Schedule = applyGreedyFusion(Schedule, Validity); @@ -905,14 +894,36 @@ static void runIslScheduleOptimizer( /*PatternOpts=*/!HasUserTransformation && PMBasedOpts, /*Postopts=*/!HasUserTransformation && EnablePostopts, /*Prevect=*/PollyVectorizerChoice != VECTORIZER_NONE, - DepsChanged}; - if (OAI.PatternOpts || OAI.Postopts || OAI.Prevect) { + DepsChanged, + MaxOpGuard}; + if (!Schedule.is_null() && (OAI.PatternOpts || OAI.Postopts || OAI.Prevect)) { Schedule = ScheduleTreeOptimizer::optimizeSchedule(Schedule, &OAI); Schedule = hoistExtensionNodes(Schedule); POLLY_DEBUG(printSchedule(dbgs(), Schedule, "After post-optimizations")); walkScheduleTreeForStatistics(Schedule, 2); } + // Check for why any computation could have failed + if (MaxOpGuard.hasQuotaExceeded()) { + POLLY_DEBUG(dbgs() << "Schedule optimizer calculation exceeds ISL quota\n"); + return; + } else if (isl_ctx_last_error(Ctx) != isl_error_none) { + POLLY_DEBUG({ + const char *File = isl_ctx_last_error_file(Ctx); + int Line = isl_ctx_last_error_line(Ctx); + const char *Msg = isl_ctx_last_error_msg(Ctx); + dbgs() << "ISL reported an error during the computation of a new " + "schedule at " + << File << ":" << Line << ": " << Msg; + }); + isl_ctx_reset_error(Ctx); + return; + } else if (Schedule.is_null()) { + POLLY_DEBUG(dbgs() << "Schedule optimizer did not compute a new schedule " + "for unknown reasons\n"); + return; + } + // Skip profitability check if user transformation(s) have been applied. if (!HasUserTransformation && !ScheduleTreeOptimizer::isProfitableSchedule(S, Schedule)) @@ -931,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; @@ -978,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/ScheduleTreeTransform.cpp b/polly/lib/Transform/ScheduleTreeTransform.cpp index 3f36300..c95c558 100644 --- a/polly/lib/Transform/ScheduleTreeTransform.cpp +++ b/polly/lib/Transform/ScheduleTreeTransform.cpp @@ -972,6 +972,9 @@ BandAttr *polly::getBandAttr(isl::schedule_node MarkOrBand) { } isl::schedule polly::hoistExtensionNodes(isl::schedule Sched) { + if (Sched.is_null()) + return {}; + // If there is no extension node in the first place, return the original // schedule tree. if (!containsExtensionNode(Sched)) @@ -1126,6 +1129,8 @@ isl::set polly::getPartialTilePrefixes(isl::set ScheduleRange, isl::union_set polly::getIsolateOptions(isl::set IsolateDomain, unsigned OutDimsNum) { + if (IsolateDomain.is_null()) + return {}; unsigned Dims = unsignedFromIslSize(IsolateDomain.tuple_dim()); assert(OutDimsNum <= Dims && "The isl::set IsolateDomain is used to describe the range of schedule " 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) |
