58#include "llvm/ADT/Sequence.h"
59#include "llvm/ADT/Statistic.h"
60#include "llvm/Analysis/OptimizationRemarkEmitter.h"
61#include "llvm/Support/CommandLine.h"
73#define DEBUG_TYPE "polly-opt-isl"
75static cl::opt<std::string>
77 cl::desc(
"Only a certain kind of dependences (all/raw)"),
80static cl::opt<std::string>
82 cl::desc(
"Dependences should be simplified (yes/no)"),
86 "polly-opt-max-constant-term",
87 cl::desc(
"The maximal constant term allowed (-1 is unlimited)"), cl::Hidden,
91 "polly-opt-max-coefficient",
92 cl::desc(
"The maximal coefficient allowed (-1 is unlimited)"), cl::Hidden,
95static cl::opt<std::string>
97 cl::desc(
"Maximize the band depth (yes/no)"), cl::Hidden,
102 cl::desc(
"Bound the scheduler by maximal amount"
103 "of computational steps. "),
104 cl::Hidden, cl::init(300000), cl::ZeroOrMore,
109 cl::desc(
"Aggressively try to fuse everything"), cl::Hidden,
113 "polly-opt-outer-coincidence",
114 cl::desc(
"Try to construct schedules where the outer member of each band "
115 "satisfies the coincidence constraints (yes/no)"),
119 "polly-prevect-width",
121 "The number of loop iterations to strip-mine for pre-vectorization"),
125 cl::desc(
"Enable loop tiling"),
129 "polly-default-tile-size",
130 cl::desc(
"The default tile size (if not enough were provided by"
131 " --polly-tile-sizes)"),
136 cl::desc(
"A tile size for each loop dimension, filled "
137 "with --polly-default-tile-size"),
142 cl::desc(
"Enable a 2nd level loop of loop tiling"),
146 "polly-2nd-level-default-tile-size",
147 cl::desc(
"The default 2nd-level tile size (if not enough were provided by"
148 " --polly-2nd-level-tile-sizes)"),
153 cl::desc(
"A tile size for each loop dimension, filled "
154 "with --polly-default-tile-size"),
155 cl::Hidden, cl::CommaSeparated,
159 cl::desc(
"Enable register tiling"),
163 "polly-register-tiling-default-tile-size",
164 cl::desc(
"The default register tile size (if not enough were provided by"
165 " --polly-register-tile-sizes)"),
170 cl::desc(
"A tile size for each loop dimension, filled "
171 "with --polly-register-tile-size"),
175 "polly-pragma-based-opts",
176 cl::desc(
"Apply user-directed transformation from metadata"),
180 cl::desc(
"Optimize SCoPs using ISL"),
185 cl::desc(
"Perform optimizations based on pattern matching"),
190 cl::desc(
"Apply post-rescheduling optimizations such as "
191 "tiling (requires -polly-reschedule)"),
195 "polly-optimized-scops",
196 cl::desc(
"Polly - Dump polyhedral description of Scops optimized with "
197 "the isl scheduling optimizer and the set of post-scheduling "
198 "transformations is applied on the schedule tree"),
202 cl::desc(
"A polly pass"),
206STATISTIC(ScopsRescheduled,
"Number of scops rescheduled");
209STATISTIC(NumAffineLoopsOptimized,
"Number of affine loops optimized");
210STATISTIC(NumBoxedLoopsOptimized,
"Number of boxed loops optimized");
212#define THREE_STATISTICS(VARNAME, DESC) \
213 static Statistic VARNAME[3] = { \
214 {DEBUG_TYPE, #VARNAME "0", DESC " (original)"}, \
215 {DEBUG_TYPE, #VARNAME "1", DESC " (after scheduler)"}, \
216 {DEBUG_TYPE, #VARNAME "2", DESC " (after optimizer)"}}
225STATISTIC(FirstLevelTileOpts,
"Number of first level tiling applied");
226STATISTIC(SecondLevelTileOpts,
"Number of second level tiling applied");
227STATISTIC(RegisterTileOpts,
"Number of register tiling applied");
228STATISTIC(PrevectOpts,
"Number of strip-mining for prevectorization applied");
230 "Number of matrix multiplication patterns detected and optimized");
237struct OptimizerAdditionalInfoTy {
238 const llvm::TargetTransformInfo *TTI;
247class ScheduleTreeOptimizer final {
264 optimizeSchedule(isl::schedule Schedule,
265 const OptimizerAdditionalInfoTy *OAI =
nullptr);
280 static isl::schedule_node
281 optimizeScheduleNode(isl::schedule_node Node,
282 const OptimizerAdditionalInfoTy *OAI =
nullptr);
290 static bool isProfitableSchedule(polly::Scop &
S, isl::schedule NewSchedule);
300 static isl::schedule_node isolateFullPartialTiles(isl::schedule_node Node,
310 static bool isTileableBandNode(isl::schedule_node Node);
320 static bool isPMOptimizableBandNode(isl::schedule_node Node);
353 static isl::schedule_node prevectSchedBand(isl::schedule_node Node,
354 unsigned DimToVectorize,
378 static isl::schedule_node applyTileBandOpt(isl::schedule_node Node);
383 static isl::schedule_node applyPrevectBandOpt(isl::schedule_node Node);
387ScheduleTreeOptimizer::isolateFullPartialTiles(isl::schedule_node Node,
394 isl::union_set ScheduleRangeUSet = SchedRelUMap.
range();
395 isl::set ScheduleRange{ScheduleRangeUSet};
400 isl::union_set Options = IsolateOption.
unite(AtomicOption);
403 isl::schedule_node_band Result =
404 Node.
as<isl::schedule_node_band>().set_ast_build_options(Options);
408struct InsertSimdMarkers final : ScheduleNodeRewriter<InsertSimdMarkers> {
409 isl::schedule_node visitBand(isl::schedule_node_band Band) {
410 isl::schedule_node Node = visitChildren(Band);
421isl::schedule_node ScheduleTreeOptimizer::prevectSchedBand(
422 isl::schedule_node Node,
unsigned DimToVectorize,
int VectorWidth) {
431 assert(DimToVectorize < ScheduleDimensions);
433 if (DimToVectorize > 0) {
436 Node = Node.
child(0);
438 if (DimToVectorize < ScheduleDimensions - 1)
442 Sizes = Sizes.set_val(0, isl::val(Node.
ctx(), VectorWidth));
445 Node = isolateFullPartialTiles(Node, VectorWidth);
446 Node = Node.
child(0);
449 Node = Node.
as<isl::schedule_node_band>().set_ast_build_options(
450 isl::union_set(Node.
ctx(),
"{ unroll[x]: 1 = 0 }"));
459 InsertSimdMarkers SimdMarkerInserter;
460 Node = SimdMarkerInserter.visit(Node);
467static bool isSimpleInnermostBand(
const isl::schedule_node &Node) {
479 auto Sequence = Node.
child(0);
483 auto Child = Sequence.child(c);
496static bool isOneTimeParentBandNode(isl::schedule_node Node) {
506bool ScheduleTreeOptimizer::isTileableBandNode(isl::schedule_node Node) {
507 if (!isOneTimeParentBandNode(Node))
518 return isSimpleInnermostBand(Node);
521bool ScheduleTreeOptimizer::isPMOptimizableBandNode(isl::schedule_node Node) {
522 if (!isOneTimeParentBandNode(Node))
525 return Node.
child(0).
isa<isl::schedule_node_leaf>();
529ScheduleTreeOptimizer::applyTileBandOpt(isl::schedule_node Node) {
533 FirstLevelTileOpts++;
539 SecondLevelTileOpts++;
552ScheduleTreeOptimizer::applyPrevectBandOpt(isl::schedule_node Node) {
558 for (
int i = Dims - 1; i >= 0; i--)
559 if (Node.
as<isl::schedule_node_band>().member_get_coincident(i)) {
570 const OptimizerAdditionalInfoTy *OAI =
571 static_cast<const OptimizerAdditionalInfoTy *
>(User);
572 assert(OAI &&
"Expecting optimization options");
576 if (OAI->PatternOpts && isPMOptimizableBandNode(Node)) {
577 isl::schedule_node PatternOptimizedSchedule =
579 if (!PatternOptimizedSchedule.
is_null()) {
581 OAI->DepsChanged =
true;
582 return PatternOptimizedSchedule.
release();
586 if (!isTileableBandNode(Node))
590 Node = applyTileBandOpt(Node);
593 IslQuotaScope MaxScope = OAI->MaxOpGuard.
enter();
597 Node = applyPrevectBandOpt(Node);
600 return (isl::schedule_node()).release();
607ScheduleTreeOptimizer::optimizeSchedule(isl::schedule Schedule,
608 const OptimizerAdditionalInfoTy *OAI) {
610 Root = optimizeScheduleNode(Root, OAI);
611 return Root.get_schedule();
614isl::schedule_node ScheduleTreeOptimizer::optimizeScheduleNode(
615 isl::schedule_node Node,
const OptimizerAdditionalInfoTy *OAI) {
618 const_cast<void *
>(
static_cast<const void *
>(OAI))));
622bool ScheduleTreeOptimizer::isProfitableSchedule(Scop &
S,
623 isl::schedule NewSchedule) {
636 auto NewScheduleMap = NewSchedule.
get_map();
637 auto OldSchedule =
S.getSchedule();
638 assert(!OldSchedule.is_null() &&
639 "Only IslScheduleOptimizer can insert extension nodes "
640 "that make Scop::getSchedule() return nullptr.");
641 bool changed = !OldSchedule.is_equal(NewScheduleMap);
646static void printSchedule(llvm::raw_ostream &OS,
const isl::schedule &Schedule,
648 isl::ctx
Ctx = Schedule.
ctx();
653 OS << Desc <<
": \n" <<
Str <<
"\n";
668static void walkScheduleTreeForStatistics(isl::schedule Schedule,
int Version) {
676 isl::schedule_node Node = isl::manage_copy(nodeptr);
677 int Version = *static_cast<int *>(user);
679 switch (isl_schedule_node_get_type(Node.get())) {
680 case isl_schedule_node_band: {
682 if (isl_schedule_node_band_get_permutable(Node.get()) ==
684 NumPermutable[Version]++;
686 int CountMembers = isl_schedule_node_band_n_member(Node.get());
687 NumBandMembers[Version] += CountMembers;
688 for (int i = 0; i < CountMembers; i += 1) {
689 if (Node.as<isl::schedule_node_band>().member_get_coincident(i))
690 NumCoincident[Version]++;
695 case isl_schedule_node_filter:
696 NumFilters[Version]++;
699 case isl_schedule_node_extension:
700 NumExtension[Version]++;
712static void runIslScheduleOptimizerImpl(
715 TargetTransformInfo *TTI, OptimizationRemarkEmitter *ORE,
719 if (
S.getSize() == 0) {
728 walkScheduleTreeForStatistics(
S.getScheduleTree(), 0);
729 POLLY_DEBUG(printSchedule(dbgs(), Schedule,
"Original schedule tree"));
731 bool HasUserTransformation =
false;
735 if (ManuallyTransformed.
is_null()) {
736 POLLY_DEBUG(dbgs() <<
"Error during manual optimization\n");
740 if (ManuallyTransformed.
get() != Schedule.
get()) {
742 HasUserTransformation =
true;
743 Schedule = std::move(ManuallyTransformed);
745 printSchedule(dbgs(), Schedule,
"After manual transformations"));
753 if (!HasUserTransformation &&
S.hasDisableHeuristicsHint()) {
754 POLLY_DEBUG(dbgs() <<
"Heuristic optimizations disabled by metadata\n");
761 POLLY_DEBUG(dbgs() <<
"DependenceInfo for another SCoP/isl_ctx\n");
765 POLLY_DEBUG(dbgs() <<
"Dependency information not available\n");
779 POLLY_DEBUG(dbgs() <<
"Skipping rescheduling due to command line option\n");
780 }
else if (HasUserTransformation) {
782 dbgs() <<
"Skipping rescheduling due to manual transformation\n");
795 errs() <<
"Do not know how to optimize for '" <<
OptimizeDeps <<
"'"
796 <<
" Falling back to optimizing all dependences.\n";
823 <<
"warning: Option -polly-opt-simplify-deps should either be 'yes' "
824 "or 'no'. Falling back to default: 'yes'\n";
827 POLLY_DEBUG(dbgs() <<
"\n\nCompute schedule from: ");
829 POLLY_DEBUG(dbgs() <<
"Proximity := " << Proximity <<
";\n");
830 POLLY_DEBUG(dbgs() <<
"Validity := " << Validity <<
";\n");
832 int IslMaximizeBands;
834 IslMaximizeBands = 1;
836 IslMaximizeBands = 0;
839 <<
"warning: Option -polly-opt-maximize-bands should either be 'yes'"
840 " or 'no'. Falling back to default: 'yes'\n";
841 IslMaximizeBands = 1;
844 int IslOuterCoincidence;
846 IslOuterCoincidence = 1;
848 IslOuterCoincidence = 0;
850 errs() <<
"warning: Option -polly-opt-outer-coincidence should either be "
851 "'yes' or 'no'. Falling back to default: 'no'\n";
852 IslOuterCoincidence = 0;
865 SC = SC.set_proximity(Proximity);
866 SC = SC.set_validity(Validity);
867 SC = SC.set_coincidence(Validity);
871 Schedule = SC.compute_schedule();
878 POLLY_DEBUG(printSchedule(dbgs(), Schedule,
"After rescheduling"));
881 walkScheduleTreeForStatistics(Schedule, 1);
891 const OptimizerAdditionalInfoTy OAI = {
899 if (!Schedule.
is_null() && (OAI.PatternOpts || OAI.Postopts || OAI.Prevect)) {
900 Schedule = ScheduleTreeOptimizer::optimizeSchedule(Schedule, &OAI);
902 POLLY_DEBUG(printSchedule(dbgs(), Schedule,
"After post-optimizations"));
903 walkScheduleTreeForStatistics(Schedule, 2);
907 if (MaxOpGuard.hasQuotaExceeded()) {
908 POLLY_DEBUG(dbgs() <<
"Schedule optimizer calculation exceeds ISL quota\n");
915 dbgs() <<
"ISL reported an error during the computation of a new "
917 << File <<
":" << Line <<
": " << Msg;
921 }
else if (Schedule.
is_null()) {
922 POLLY_DEBUG(dbgs() <<
"Schedule optimizer did not compute a new schedule "
923 "for unknown reasons\n");
928 if (!HasUserTransformation &&
929 !ScheduleTreeOptimizer::isProfitableSchedule(
S, Schedule))
932 auto ScopStats =
S.getStatistics();
934 NumAffineLoopsOptimized += ScopStats.NumAffineLoops;
935 NumBoxedLoopsOptimized += ScopStats.NumBoxedLoops;
936 LastSchedule = Schedule;
938 S.setScheduleTree(Schedule);
945static void runScheduleOptimizerPrinter(raw_ostream &OS,
950 OS <<
"Calculated schedule:\n";
963 OS << ScheduleStr <<
"\n";
975 OptimizationRemarkEmitter ORE(&
S.getFunction());
977 bool DepsChanged =
false;
978 runIslScheduleOptimizerImpl(
S, GetDeps, TTI, &ORE, LastSchedule, DepsChanged);
984 <<
"Printing analysis 'Polly - Optimize schedule of SCoP' for region: '"
985 <<
S.getName() <<
"' in function '" <<
S.getFunction().getName()
987 runScheduleOptimizerPrinter(outs(), LastSchedule);
llvm::cl::OptionCategory PollyCategory
static cl::opt< bool > PragmaBasedOpts("polly-pragma-based-opts", cl::desc("Apply user-directed transformation from metadata"), cl::init(true), cl::cat(PollyCategory))
static cl::opt< int > MaxCoefficient("polly-opt-max-coefficient", cl::desc("The maximal coefficient allowed (-1 is unlimited)"), cl::Hidden, cl::init(20), cl::cat(PollyCategory))
static cl::opt< bool > PollyPrintOptIsl("polly-print-opt-isl", cl::desc("A polly pass"), cl::cat(PollyCategory))
static cl::opt< int > MaxConstantTerm("polly-opt-max-constant-term", cl::desc("The maximal constant term allowed (-1 is unlimited)"), cl::Hidden, cl::init(20), cl::cat(PollyCategory))
static cl::opt< int > PrevectorWidth("polly-prevect-width", cl::desc("The number of loop iterations to strip-mine for pre-vectorization"), cl::Hidden, cl::init(4), cl::cat(PollyCategory))
static cl::opt< std::string > MaximizeBandDepth("polly-opt-maximize-bands", cl::desc("Maximize the band depth (yes/no)"), cl::Hidden, cl::init("yes"), cl::cat(PollyCategory))
static cl::opt< int > SecondLevelDefaultTileSize("polly-2nd-level-default-tile-size", cl::desc("The default 2nd-level tile size (if not enough were provided by" " --polly-2nd-level-tile-sizes)"), cl::Hidden, cl::init(16), cl::cat(PollyCategory))
static cl::opt< int > RegisterDefaultTileSize("polly-register-tiling-default-tile-size", cl::desc("The default register tile size (if not enough were provided by" " --polly-register-tile-sizes)"), cl::Hidden, cl::init(2), cl::cat(PollyCategory))
static cl::opt< int > FirstLevelDefaultTileSize("polly-default-tile-size", cl::desc("The default tile size (if not enough were provided by" " --polly-tile-sizes)"), cl::Hidden, cl::init(32), cl::cat(PollyCategory))
static cl::opt< int > ScheduleComputeOut("polly-schedule-computeout", cl::desc("Bound the scheduler by maximal amount" "of computational steps. "), cl::Hidden, cl::init(300000), cl::ZeroOrMore, cl::cat(PollyCategory))
static cl::opt< bool > OptimizedScops("polly-optimized-scops", cl::desc("Polly - Dump polyhedral description of Scops optimized with " "the isl scheduling optimizer and the set of post-scheduling " "transformations is applied on the schedule tree"), cl::cat(PollyCategory))
static cl::opt< bool > PMBasedOpts("polly-pattern-matching-based-opts", cl::desc("Perform optimizations based on pattern matching"), cl::init(true), cl::cat(PollyCategory))
static cl::opt< bool > EnablePostopts("polly-postopts", cl::desc("Apply post-rescheduling optimizations such as " "tiling (requires -polly-reschedule)"), cl::init(true), cl::cat(PollyCategory))
static cl::opt< bool > FirstLevelTiling("polly-tiling", cl::desc("Enable loop tiling"), cl::init(true), cl::cat(PollyCategory))
static cl::list< int > FirstLevelTileSizes("polly-tile-sizes", cl::desc("A tile size for each loop dimension, filled " "with --polly-default-tile-size"), cl::Hidden, cl::CommaSeparated, cl::cat(PollyCategory))
static cl::opt< bool > GreedyFusion("polly-loopfusion-greedy", cl::desc("Aggressively try to fuse everything"), cl::Hidden, cl::cat(PollyCategory))
static cl::opt< bool > RegisterTiling("polly-register-tiling", cl::desc("Enable register tiling"), cl::cat(PollyCategory))
static cl::opt< std::string > SimplifyDeps("polly-opt-simplify-deps", cl::desc("Dependences should be simplified (yes/no)"), cl::Hidden, cl::init("yes"), cl::cat(PollyCategory))
static cl::opt< bool > EnableReschedule("polly-reschedule", cl::desc("Optimize SCoPs using ISL"), cl::init(true), cl::cat(PollyCategory))
STATISTIC(ScopsProcessed, "Number of scops processed")
static cl::opt< bool > SecondLevelTiling("polly-2nd-level-tiling", cl::desc("Enable a 2nd level loop of loop tiling"), cl::cat(PollyCategory))
static cl::opt< std::string > OptimizeDeps("polly-opt-optimize-only", cl::desc("Only a certain kind of dependences (all/raw)"), cl::Hidden, cl::init("all"), cl::cat(PollyCategory))
static cl::list< int > RegisterTileSizes("polly-register-tile-sizes", cl::desc("A tile size for each loop dimension, filled " "with --polly-register-tile-size"), cl::Hidden, cl::CommaSeparated, cl::cat(PollyCategory))
#define THREE_STATISTICS(VARNAME, DESC)
static cl::list< int > SecondLevelTileSizes("polly-2nd-level-tile-sizes", cl::desc("A tile size for each loop dimension, filled " "with --polly-default-tile-size"), cl::Hidden, cl::CommaSeparated, cl::cat(PollyCategory))
static cl::opt< std::string > OuterCoincidence("polly-opt-outer-coincidence", cl::desc("Try to construct schedules where the outer member of each band " "satisfies the coincidence constraints (yes/no)"), cl::Hidden, cl::init("no"), cl::cat(PollyCategory))
static isl::id alloc(isl::ctx ctx, const std::string &name, void *user)
static isl::multi_val zero(isl::space space)
static isl::schedule_constraints on_domain(isl::union_set domain)
isl::schedule_node insert_mark(isl::id mark) const
isl::schedule_node child(int pos) const
__isl_give isl_schedule_node * release()
isl::union_map get_prefix_schedule_relation() const
isl::schedule_node parent() const
isl::schedule_node first_child() const
__isl_keep isl_schedule_node * get() const
__isl_keep isl_schedule * get() const
isl::schedule_node get_root() const
isl::union_map get_map() const
isl::union_set range() const
isl::union_map gist_domain(isl::union_set uset) const
isl::union_map gist_range(isl::union_set uset) const
isl::union_set unite(isl::union_set uset2) const
The accumulated dependence information for a SCoP.
bool hasValidDependences() const
Report if valid dependences are available.
const std::shared_ptr< isl_ctx > & getSharedIslCtx() const
isl::union_map getDependences(int Kinds) const
Get the dependences of type Kinds.
Scoped limit of ISL operations.
bool hasQuotaExceeded() const
Return whether the current quota has exceeded.
IslQuotaScope enter(bool AllowReturnNull=true)
Enter a scope that can handle out-of-quota errors.
Scope guard for code that allows arbitrary isl function to return an error if the max-operations quot...
const char * isl_ctx_last_error_file(isl_ctx *ctx)
enum isl_error isl_ctx_last_error(isl_ctx *ctx)
void isl_ctx_reset_error(isl_ctx *ctx)
int isl_ctx_last_error_line(isl_ctx *ctx)
const char * isl_ctx_last_error_msg(isl_ctx *ctx)
isl_stat isl_stat void * user
enum isl_schedule_node_type isl_schedule_node_get_type(__isl_keep isl_schedule_node *node)
boolean manage(isl_bool val)
isl::schedule applyManualTransformations(Scop *S, isl::schedule Sched, const Dependences &D, llvm::OptimizationRemarkEmitter *ORE)
Apply loop-transformation metadata.
VectorizerChoice PollyVectorizerChoice
isl::schedule_node applyRegisterTiling(isl::schedule_node Node, llvm::ArrayRef< int > TileSizes, int DefaultTileSize)
Tile a schedule node and unroll point loops.
isl::schedule applyGreedyFusion(isl::schedule Sched, const isl::union_map &Deps)
Apply greedy fusion.
isl::schedule_node tryOptimizeMatMulPattern(isl::schedule_node Node, const llvm::TargetTransformInfo *TTI, const Dependences *D)
Apply the BLIS matmul optimization pattern if possible.
isl::union_set getIsolateOptions(isl::set IsolateDomain, unsigned OutDimsNum)
Create an isl::union_set, which describes the isolate option based on IsolateDomain.
void runIslScheduleOptimizer(Scop &S, llvm::TargetTransformInfo *TTI, DependenceAnalysis::Result &Deps)
isl::schedule_node tileNode(isl::schedule_node Node, const char *Identifier, llvm::ArrayRef< int > TileSizes, int DefaultTileSize)
Tile a schedule node.
isl::union_set getDimOptions(isl::ctx Ctx, const char *Option)
Create an isl::union_set, which describes the specified option for the dimension of the current node.
isl::schedule hoistExtensionNodes(isl::schedule Sched)
Hoist all domains from extension into the root domain node, such that there are no more extension nod...
isl::set getPartialTilePrefixes(isl::set ScheduleRange, int VectorWidth)
Build the desired set of partial tile prefixes.
isl_stat isl_options_set_on_error(isl_ctx *ctx, int val)
int isl_options_get_on_error(isl_ctx *ctx)
#define ISL_ON_ERROR_CONTINUE
__isl_null isl_printer * isl_printer_free(__isl_take isl_printer *printer)
__isl_give char * isl_printer_get_str(__isl_keep isl_printer *printer)
#define ISL_YAML_STYLE_BLOCK
__isl_give isl_printer * isl_printer_set_yaml_style(__isl_take isl_printer *p, int yaml_style)
__isl_give isl_printer * isl_printer_to_str(isl_ctx *ctx)
struct isl_printer isl_printer
isl_stat isl_options_set_schedule_outer_coincidence(isl_ctx *ctx, int val)
isl_stat isl_options_set_schedule_maximize_band_depth(isl_ctx *ctx, int val)
__isl_give isl_printer * isl_printer_print_schedule(__isl_take isl_printer *p, __isl_keep isl_schedule *schedule)
isl_stat isl_options_set_schedule_max_constant_term(isl_ctx *ctx, int val)
isl_stat isl_options_set_schedule_max_coefficient(isl_ctx *ctx, int val)
__isl_give isl_schedule_node * isl_schedule_node_band_sink(__isl_take isl_schedule_node *node)
__isl_export __isl_give isl_schedule_node * isl_schedule_node_band_split(__isl_take isl_schedule_node *node, int pos)
__isl_export isl_size isl_schedule_node_n_children(__isl_keep isl_schedule_node *node)
__isl_export __isl_give isl_schedule_node * isl_schedule_node_band_tile(__isl_take isl_schedule_node *node, __isl_take isl_multi_val *sizes)
__isl_export isl_stat isl_schedule_node_foreach_descendant_top_down(__isl_keep isl_schedule_node *node, isl_bool(*fn)(__isl_keep isl_schedule_node *node, void *user), void *user)
__isl_give isl_space * isl_schedule_node_band_get_space(__isl_keep isl_schedule_node *node)
__isl_export __isl_give isl_schedule_node * isl_schedule_node_map_descendant_bottom_up(__isl_take isl_schedule_node *node, __isl_give isl_schedule_node *(*fn)(__isl_take isl_schedule_node *node, void *user), void *user)
isl_stat isl_options_set_tile_scale_tile_loops(isl_ctx *ctx, int val)
__isl_export isl_bool isl_schedule_node_band_get_permutable(__isl_keep isl_schedule_node *node)
struct isl_schedule_node isl_schedule_node
@ isl_schedule_node_filter
@ isl_schedule_node_sequence
const Dependences & getDependences(Dependences::AnalysisLevel Level)
Return the dependence information for the current SCoP.
void abandonDependences()
Invalidate the dependence information and recompute it when needed again.
static TupleKindPtr Domain("Domain")