diff options
Diffstat (limited to 'polly/lib/Transform/ScheduleOptimizer.cpp')
| -rw-r--r-- | polly/lib/Transform/ScheduleOptimizer.cpp | 205 | 
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)  | 
