aboutsummaryrefslogtreecommitdiff
path: root/polly/lib/Transform/ScheduleOptimizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'polly/lib/Transform/ScheduleOptimizer.cpp')
-rw-r--r--polly/lib/Transform/ScheduleOptimizer.cpp205
1 files changed, 59 insertions, 146 deletions
diff --git a/polly/lib/Transform/ScheduleOptimizer.cpp b/polly/lib/Transform/ScheduleOptimizer.cpp
index 070700a..6acdd68 100644
--- a/polly/lib/Transform/ScheduleOptimizer.cpp
+++ b/polly/lib/Transform/ScheduleOptimizer.cpp
@@ -57,7 +57,6 @@
#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 +197,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 +240,7 @@ struct OptimizerAdditionalInfoTy {
bool Postopts;
bool Prevect;
bool &DepsChanged;
+ IslMaxOperationsGuard &MaxOpGuard;
};
class ScheduleTreeOptimizer final {
@@ -381,6 +385,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 +397,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 +419,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 +451,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 +550,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 +589,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 +641,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 +708,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 +765,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 +851,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 +866,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 +893,20 @@ 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);
}
+ if (MaxOpGuard.hasQuotaExceeded()) {
+ POLLY_DEBUG(dbgs() << "Schedule optimizer calculation exceeds ISL quota\n");
+ return;
+ }
+
// Skip profitability check if user transformation(s) have been applied.
if (!HasUserTransformation &&
!ScheduleTreeOptimizer::isProfitableSchedule(S, Schedule))
@@ -931,30 +925,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,36 +948,8 @@ 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,
@@ -1020,7 +962,7 @@ runIslScheduleOptimizerUsingNPM(Scop &S, ScopAnalysisManager &SAM,
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();
@@ -1046,52 +988,23 @@ IslScheduleOptimizerPrinterPass::run(Scop &S, ScopAnalysisManager &SAM,
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 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());
+ isl::schedule LastSchedule;
+ bool DepsChanged = false;
+ runIslScheduleOptimizerImpl(S, GetDeps, TTI, &ORE, LastSchedule, DepsChanged);
+ if (DepsChanged)
+ Deps.abandonDependences();
- void getAnalysisUsage(AnalysisUsage &AU) const override {
- ScopPass::getAnalysisUsage(AU);
- AU.addRequired<IslScheduleOptimizerWrapperPass>();
- AU.setPreservesAll();
+ if (PollyPrintOptIsl) {
+ outs()
+ << "Printing analysis 'Polly - Optimize schedule of SCoP' for region: '"
+ << S.getName() << "' in function '" << S.getFunction().getName()
+ << "':\n";
+ runScheduleOptimizerPrinter(outs(), LastSchedule);
}
-
-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)