blob: 7f0f731ddd4dd9880428abb546257dd53e06293c [file] [log] [blame]
Tobias Grosser30aa24c2011-05-14 19:02:06 +00001//===- Schedule.cpp - Calculate an optimized schedule ---------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This pass the isl to calculate a schedule that is optimized for parallelism
11// and tileablility. The algorithm used in isl is an optimized version of the
12// algorithm described in following paper:
13//
14// U. Bondhugula, A. Hartono, J. Ramanujam, and P. Sadayappan.
15// A Practical Automatic Polyhedral Parallelizer and Locality Optimizer.
16// In Proceedings of the 2008 ACM SIGPLAN Conference On Programming Language
17// Design and Implementation, PLDI ’08, pages 101–113. ACM, 2008.
18//===----------------------------------------------------------------------===//
19
Tobias Grosser967239c2011-10-23 20:59:44 +000020#include "polly/ScheduleOptimizer.h"
21
Tobias Grosser67707b72011-10-23 20:59:40 +000022#include "polly/CodeGeneration.h"
Tobias Grosser30aa24c2011-05-14 19:02:06 +000023#include "polly/Dependences.h"
Tobias Grosser8ad6bc32012-01-31 13:26:29 +000024#include "polly/LinkAllPasses.h"
Tobias Grosser30aa24c2011-05-14 19:02:06 +000025#include "polly/ScopInfo.h"
26
Tobias Grosser2493e922011-12-07 07:42:57 +000027#include "isl/aff.h"
Tobias Grosserde68cc92011-06-30 20:01:02 +000028#include "isl/band.h"
Tobias Grosser8ad6bc32012-01-31 13:26:29 +000029#include "isl/constraint.h"
30#include "isl/map.h"
Tobias Grosser42152ff2012-01-30 19:38:47 +000031#include "isl/options.h"
Tobias Grosser8ad6bc32012-01-31 13:26:29 +000032#include "isl/schedule.h"
33#include "isl/space.h"
Tobias Grosser30aa24c2011-05-14 19:02:06 +000034
Tobias Grosser4dca4392011-11-22 19:40:19 +000035#define DEBUG_TYPE "polly-opt-isl"
Tobias Grosser30aa24c2011-05-14 19:02:06 +000036#include "llvm/Support/Debug.h"
Tobias Grosserc6699b72011-06-30 20:29:13 +000037#include "llvm/Support/CommandLine.h"
Tobias Grosser30aa24c2011-05-14 19:02:06 +000038
39using namespace llvm;
40using namespace polly;
41
Tobias Grosser967239c2011-10-23 20:59:44 +000042namespace polly {
43 bool DisablePollyTiling;
44}
45static cl::opt<bool, true>
Tobias Grosser353a2682011-10-23 20:59:26 +000046DisableTiling("polly-no-tiling",
Tobias Grosser967239c2011-10-23 20:59:44 +000047 cl::desc("Disable tiling in the scheduler"), cl::Hidden,
48 cl::location(polly::DisablePollyTiling), cl::init(false));
Tobias Grosser353a2682011-10-23 20:59:26 +000049
Tobias Grossera26db472012-01-30 19:38:43 +000050static cl::opt<std::string>
Tobias Grosser1deda292012-02-14 14:02:48 +000051OptimizeDeps("polly-opt-optimize-only",
52 cl::desc("Only a certain kind of dependences (all/raw)"),
53 cl::Hidden, cl::init("all"));
54
55static cl::opt<std::string>
Tobias Grossera26db472012-01-30 19:38:43 +000056SimplifyDeps("polly-opt-simplify-deps",
57 cl::desc("Dependences should be simplified (yes/no)"),
58 cl::Hidden, cl::init("yes"));
59
Tobias Grosserb3ad85b2012-01-30 19:38:50 +000060static cl::opt<std::string>
61FusionStrategy("polly-opt-fusion",
62 cl::desc("The fusion strategy to choose (min/max)"),
Tobias Grosser50ff31d2012-01-30 19:38:58 +000063 cl::Hidden, cl::init("min"));
Tobias Grosserb3ad85b2012-01-30 19:38:50 +000064
Tobias Grosser95e860c2012-01-30 19:38:54 +000065static cl::opt<std::string>
Tobias Grossera4ea90b2012-01-30 22:43:56 +000066MaximizeBandDepth("polly-opt-maximize-bands",
67 cl::desc("Maximize the band depth (yes/no)"),
Tobias Grosser95e860c2012-01-30 19:38:54 +000068 cl::Hidden, cl::init("yes"));
69
Tobias Grosser30aa24c2011-05-14 19:02:06 +000070namespace {
71
Tobias Grosser73600b82011-10-08 00:30:40 +000072 class IslScheduleOptimizer : public ScopPass {
Tobias Grosser30aa24c2011-05-14 19:02:06 +000073
74 public:
75 static char ID;
Tobias Grosser73600b82011-10-08 00:30:40 +000076 explicit IslScheduleOptimizer() : ScopPass(ID) {}
Tobias Grosser30aa24c2011-05-14 19:02:06 +000077
78 virtual bool runOnScop(Scop &S);
79 void printScop(llvm::raw_ostream &OS) const;
80 void getAnalysisUsage(AnalysisUsage &AU) const;
81 };
82
83}
84
Tobias Grosser73600b82011-10-08 00:30:40 +000085char IslScheduleOptimizer::ID = 0;
Tobias Grosser30aa24c2011-05-14 19:02:06 +000086
87static int getSingleMap(__isl_take isl_map *map, void *user) {
88 isl_map **singleMap = (isl_map **) user;
89 *singleMap = map;
90
91 return 0;
92}
93
Tobias Grossercf3942d2011-10-06 00:04:05 +000094static void extendScattering(Scop &S, unsigned NewDimensions) {
Tobias Grosser30aa24c2011-05-14 19:02:06 +000095 for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) {
Tobias Grossercf3942d2011-10-06 00:04:05 +000096 ScopStmt *Stmt = *SI;
Tobias Grosser30aa24c2011-05-14 19:02:06 +000097
Tobias Grossercf3942d2011-10-06 00:04:05 +000098 if (Stmt->isFinalRead())
Tobias Grosser30aa24c2011-05-14 19:02:06 +000099 continue;
100
Tobias Grossercf3942d2011-10-06 00:04:05 +0000101 unsigned OldDimensions = Stmt->getNumScattering();
102 isl_space *Space;
103 isl_basic_map *ChangeScattering;
104
105 Space = isl_space_alloc(Stmt->getIslCtx(), 0, OldDimensions, NewDimensions);
106 ChangeScattering = isl_basic_map_universe(isl_space_copy(Space));
Tobias Grosserf5338802011-10-06 00:03:35 +0000107 isl_local_space *LocalSpace = isl_local_space_from_space(Space);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000108
Tobias Grossercf3942d2011-10-06 00:04:05 +0000109 for (unsigned i = 0; i < OldDimensions; i++) {
Tobias Grosserf5338802011-10-06 00:03:35 +0000110 isl_constraint *c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000111 isl_constraint_set_coefficient_si(c, isl_dim_in, i, 1);
112 isl_constraint_set_coefficient_si(c, isl_dim_out, i, -1);
Tobias Grossercf3942d2011-10-06 00:04:05 +0000113 ChangeScattering = isl_basic_map_add_constraint(ChangeScattering, c);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000114 }
115
Tobias Grossercf3942d2011-10-06 00:04:05 +0000116 for (unsigned i = OldDimensions; i < NewDimensions; i++) {
Tobias Grosserf5338802011-10-06 00:03:35 +0000117 isl_constraint *c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000118 isl_constraint_set_coefficient_si(c, isl_dim_out, i, 1);
Tobias Grossercf3942d2011-10-06 00:04:05 +0000119 ChangeScattering = isl_basic_map_add_constraint(ChangeScattering, c);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000120 }
121
Tobias Grossercf3942d2011-10-06 00:04:05 +0000122 isl_map *ChangeScatteringMap = isl_map_from_basic_map(ChangeScattering);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000123
Tobias Grossercf3942d2011-10-06 00:04:05 +0000124 ChangeScatteringMap = isl_map_align_params(ChangeScatteringMap,
125 S.getParamSpace());
126 isl_map *NewScattering = isl_map_apply_range(Stmt->getScattering(),
127 ChangeScatteringMap);
128 Stmt->setScattering(NewScattering);
Tobias Grosserf5338802011-10-06 00:03:35 +0000129 isl_local_space_free(LocalSpace);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000130 }
131}
132
Tobias Grosserde68cc92011-06-30 20:01:02 +0000133// getTileMap - Create a map that describes a n-dimensonal tiling.
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000134//
Tobias Grosserde68cc92011-06-30 20:01:02 +0000135// getTileMap creates a map from a n-dimensional scattering space into an
136// 2*n-dimensional scattering space. The map describes a rectangular tiling.
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000137//
Tobias Grosserde68cc92011-06-30 20:01:02 +0000138// Example:
139// scheduleDimensions = 2, parameterDimensions = 1, tileSize = 32
140//
141// tileMap := [p0] -> {[s0, s1] -> [t0, t1, s0, s1]:
142// t0 % 32 = 0 and t0 <= s0 < t0 + 32 and
143// t1 % 32 = 0 and t1 <= s1 < t1 + 32}
144//
145// Before tiling:
146//
147// for (i = 0; i < N; i++)
148// for (j = 0; j < M; j++)
149// S(i,j)
150//
151// After tiling:
152//
153// for (t_i = 0; t_i < N; i+=32)
154// for (t_j = 0; t_j < M; j+=32)
155// for (i = t_i; i < min(t_i + 32, N); i++) | Unknown that N % 32 = 0
156// for (j = t_j; j < t_j + 32; j++) | Known that M % 32 = 0
157// S(i,j)
158//
159static isl_basic_map *getTileMap(isl_ctx *ctx, int scheduleDimensions,
Tobias Grosserf5338802011-10-06 00:03:35 +0000160 isl_space *SpaceModel, int tileSize = 32) {
Tobias Grosserde68cc92011-06-30 20:01:02 +0000161 // We construct
162 //
163 // tileMap := [p0] -> {[s0, s1] -> [t0, t1, p0, p1, a0, a1]:
164 // s0 = a0 * 32 and s0 = p0 and t0 <= p0 < t0 + 32 and
165 // s1 = a1 * 32 and s1 = p1 and t1 <= p1 < t1 + 32}
166 //
167 // and project out the auxilary dimensions a0 and a1.
Tobias Grosserf5338802011-10-06 00:03:35 +0000168 isl_space *Space = isl_space_alloc(ctx, 0, scheduleDimensions,
169 scheduleDimensions * 3);
170 isl_basic_map *tileMap = isl_basic_map_universe(isl_space_copy(Space));
171
172 isl_local_space *LocalSpace = isl_local_space_from_space(Space);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000173
Tobias Grosserde68cc92011-06-30 20:01:02 +0000174 for (int x = 0; x < scheduleDimensions; x++) {
175 int sX = x;
176 int tX = x;
177 int pX = scheduleDimensions + x;
178 int aX = 2 * scheduleDimensions + x;
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000179
Tobias Grosserde68cc92011-06-30 20:01:02 +0000180 isl_constraint *c;
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000181
Tobias Grosserde68cc92011-06-30 20:01:02 +0000182 // sX = aX * tileSize;
Tobias Grosserf5338802011-10-06 00:03:35 +0000183 c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
Tobias Grosserde68cc92011-06-30 20:01:02 +0000184 isl_constraint_set_coefficient_si(c, isl_dim_out, sX, 1);
185 isl_constraint_set_coefficient_si(c, isl_dim_out, aX, -tileSize);
186 tileMap = isl_basic_map_add_constraint(tileMap, c);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000187
Tobias Grosserde68cc92011-06-30 20:01:02 +0000188 // pX = sX;
Tobias Grosserf5338802011-10-06 00:03:35 +0000189 c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
Tobias Grosserde68cc92011-06-30 20:01:02 +0000190 isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1);
191 isl_constraint_set_coefficient_si(c, isl_dim_in, sX, -1);
192 tileMap = isl_basic_map_add_constraint(tileMap, c);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000193
Tobias Grosserde68cc92011-06-30 20:01:02 +0000194 // tX <= pX
Tobias Grosserf5338802011-10-06 00:03:35 +0000195 c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
Tobias Grosserde68cc92011-06-30 20:01:02 +0000196 isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1);
197 isl_constraint_set_coefficient_si(c, isl_dim_out, tX, -1);
198 tileMap = isl_basic_map_add_constraint(tileMap, c);
199
200 // pX <= tX + (tileSize - 1)
Tobias Grosserf5338802011-10-06 00:03:35 +0000201 c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
Tobias Grosserde68cc92011-06-30 20:01:02 +0000202 isl_constraint_set_coefficient_si(c, isl_dim_out, tX, 1);
203 isl_constraint_set_coefficient_si(c, isl_dim_out, pX, -1);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000204 isl_constraint_set_constant_si(c, tileSize - 1);
Tobias Grosserde68cc92011-06-30 20:01:02 +0000205 tileMap = isl_basic_map_add_constraint(tileMap, c);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000206 }
207
Tobias Grosserde68cc92011-06-30 20:01:02 +0000208 // Project out auxilary dimensions.
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000209 //
Tobias Grosserde68cc92011-06-30 20:01:02 +0000210 // The auxilary dimensions are transformed into existentially quantified ones.
211 // This reduces the number of visible scattering dimensions and allows Cloog
212 // to produces better code.
213 tileMap = isl_basic_map_project_out(tileMap, isl_dim_out,
214 2 * scheduleDimensions,
215 scheduleDimensions);
Tobias Grosserf5338802011-10-06 00:03:35 +0000216 isl_local_space_free(LocalSpace);
Tobias Grosserde68cc92011-06-30 20:01:02 +0000217 return tileMap;
218}
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000219
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000220// getScheduleForBand - Get the schedule for this band.
221//
Tobias Grosserb6033392011-12-08 13:02:58 +0000222// Polly applies transformations like tiling on top of the isl calculated value.
223// This can influence the number of scheduling dimension. The number of
224// schedule dimensions is returned in the parameter 'Dimension'.
225isl_union_map *getScheduleForBand(isl_band *Band, int *Dimensions) {
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000226 isl_union_map *PartialSchedule;
Tobias Grosserde68cc92011-06-30 20:01:02 +0000227 isl_ctx *ctx;
Tobias Grosserf5338802011-10-06 00:03:35 +0000228 isl_space *Space;
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000229 isl_basic_map *TileMap;
230 isl_union_map *TileUMap;
Tobias Grosserde68cc92011-06-30 20:01:02 +0000231
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000232 PartialSchedule = isl_band_get_partial_schedule(Band);
Tobias Grosserb6033392011-12-08 13:02:58 +0000233 *Dimensions = isl_band_n_member(Band);
Tobias Grosserde68cc92011-06-30 20:01:02 +0000234
Tobias Grosser79b30202011-11-17 12:56:00 +0000235 if (DisableTiling)
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000236 return PartialSchedule;
Tobias Grosser353a2682011-10-23 20:59:26 +0000237
Tobias Grosserb6033392011-12-08 13:02:58 +0000238 // It does not make any sense to tile a band with just one dimension.
239 if (*Dimensions == 1)
240 return PartialSchedule;
241
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000242 ctx = isl_union_map_get_ctx(PartialSchedule);
243 Space = isl_union_map_get_space(PartialSchedule);
Tobias Grosserde68cc92011-06-30 20:01:02 +0000244
Tobias Grosserb6033392011-12-08 13:02:58 +0000245 TileMap = getTileMap(ctx, *Dimensions, Space);
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000246 TileUMap = isl_union_map_from_map(isl_map_from_basic_map(TileMap));
247 TileUMap = isl_union_map_align_params(TileUMap, Space);
Tobias Grosserb6033392011-12-08 13:02:58 +0000248 *Dimensions = 2 * *Dimensions;
249
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000250 return isl_union_map_apply_range(PartialSchedule, TileUMap);
Tobias Grosserde68cc92011-06-30 20:01:02 +0000251}
252
Tobias Grosser2493e922011-12-07 07:42:57 +0000253// Create a map that pre-vectorizes one scheduling dimension.
254//
255// getPrevectorMap creates a map that maps each input dimension to the same
256// output dimension, except for the dimension DimToVectorize. DimToVectorize is
257// strip mined by 'VectorWidth' and the newly created point loop of
258// DimToVectorize is moved to the innermost level.
259//
260// Example (DimToVectorize=0, ScheduleDimensions=2, VectorWidth=4):
261//
262// | Before transformation
263// |
264// | A[i,j] -> [i,j]
265// |
266// | for (i = 0; i < 128; i++)
267// | for (j = 0; j < 128; j++)
268// | A(i,j);
269//
270// Prevector map:
271// [i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and i = ip
272//
273// | After transformation:
274// |
275// | A[i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and i = ip
276// |
277// | for (it = 0; it < 128; it+=4)
278// | for (j = 0; j < 128; j++)
279// | for (ip = max(0,it); ip < min(128, it + 3); ip++)
280// | A(ip,j);
281//
282// The goal of this transformation is to create a trivially vectorizable loop.
283// This means a parallel loop at the innermost level that has a constant number
284// of iterations corresponding to the target vector width.
285//
286// This transformation creates a loop at the innermost level. The loop has a
287// constant number of iterations, if the number of loop iterations at
288// DimToVectorize can be devided by VectorWidth. The default VectorWidth is
289// currently constant and not yet target specific. This function does not reason
290// about parallelism.
291static isl_map *getPrevectorMap(isl_ctx *ctx, int DimToVectorize,
292 int ScheduleDimensions,
293 int VectorWidth = 4) {
294 isl_space *Space;
295 isl_local_space *LocalSpace, *LocalSpaceRange;
296 isl_set *Modulo;
297 isl_map *TilingMap;
Tobias Grosserc6699b72011-06-30 20:29:13 +0000298 isl_constraint *c;
Tobias Grosser2493e922011-12-07 07:42:57 +0000299 isl_aff *Aff;
300 int PointDimension; /* ip */
301 int TileDimension; /* it */
302 isl_int VectorWidthMP;
Tobias Grosserc6699b72011-06-30 20:29:13 +0000303
Tobias Grosser2493e922011-12-07 07:42:57 +0000304 assert (0 <= DimToVectorize && DimToVectorize < ScheduleDimensions);
Tobias Grosserf5338802011-10-06 00:03:35 +0000305
Tobias Grosser2493e922011-12-07 07:42:57 +0000306 Space = isl_space_alloc(ctx, 0, ScheduleDimensions, ScheduleDimensions + 1);
307 TilingMap = isl_map_universe(isl_space_copy(Space));
308 LocalSpace = isl_local_space_from_space(Space);
309 PointDimension = ScheduleDimensions;
310 TileDimension = DimToVectorize;
311
312 // Create an identity map for everything except DimToVectorize and map
313 // DimToVectorize to the point loop at the innermost dimension.
314 for (int i = 0; i < ScheduleDimensions; i++) {
Tobias Grosserf5338802011-10-06 00:03:35 +0000315 c = isl_equality_alloc(isl_local_space_copy(LocalSpace));
Tobias Grosserc6699b72011-06-30 20:29:13 +0000316 isl_constraint_set_coefficient_si(c, isl_dim_in, i, -1);
Tobias Grosser2493e922011-12-07 07:42:57 +0000317
318 if (i == DimToVectorize)
319 isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, 1);
320 else
321 isl_constraint_set_coefficient_si(c, isl_dim_out, i, 1);
322
323 TilingMap = isl_map_add_constraint(TilingMap, c);
Tobias Grosserc6699b72011-06-30 20:29:13 +0000324 }
325
Tobias Grosser2493e922011-12-07 07:42:57 +0000326 // it % 'VectorWidth' = 0
327 LocalSpaceRange = isl_local_space_range(isl_local_space_copy(LocalSpace));
328 Aff = isl_aff_zero_on_domain(LocalSpaceRange);
329 Aff = isl_aff_set_constant_si(Aff, VectorWidth);
330 Aff = isl_aff_set_coefficient_si(Aff, isl_dim_in, TileDimension, 1);
331 isl_int_init(VectorWidthMP);
332 isl_int_set_si(VectorWidthMP, VectorWidth);
333 Aff = isl_aff_mod(Aff, VectorWidthMP);
334 isl_int_clear(VectorWidthMP);
335 Modulo = isl_pw_aff_zero_set(isl_pw_aff_from_aff(Aff));
336 TilingMap = isl_map_intersect_range(TilingMap, Modulo);
Tobias Grosserc6699b72011-06-30 20:29:13 +0000337
Tobias Grosser2493e922011-12-07 07:42:57 +0000338 // it <= ip
Tobias Grosserf5338802011-10-06 00:03:35 +0000339 c = isl_inequality_alloc(isl_local_space_copy(LocalSpace));
Tobias Grosser2493e922011-12-07 07:42:57 +0000340 isl_constraint_set_coefficient_si(c, isl_dim_out, TileDimension, -1);
341 isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, 1);
342 TilingMap = isl_map_add_constraint(TilingMap, c);
Tobias Grosserc6699b72011-06-30 20:29:13 +0000343
Tobias Grosser2493e922011-12-07 07:42:57 +0000344 // ip <= it + ('VectorWidth' - 1)
Tobias Grosserf5338802011-10-06 00:03:35 +0000345 c = isl_inequality_alloc(LocalSpace);
Tobias Grosser2493e922011-12-07 07:42:57 +0000346 isl_constraint_set_coefficient_si(c, isl_dim_out, TileDimension, 1);
347 isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, -1);
348 isl_constraint_set_constant_si(c, VectorWidth - 1);
349 TilingMap = isl_map_add_constraint(TilingMap, c);
Tobias Grosserc6699b72011-06-30 20:29:13 +0000350
Tobias Grosser2493e922011-12-07 07:42:57 +0000351 isl_map_dump(TilingMap);
Tobias Grosserc6699b72011-06-30 20:29:13 +0000352
Tobias Grosser2493e922011-12-07 07:42:57 +0000353 return TilingMap;
Tobias Grosserc6699b72011-06-30 20:29:13 +0000354}
355
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000356// getScheduleForBandList - Get the scheduling map for a list of bands.
Tobias Grosserde68cc92011-06-30 20:01:02 +0000357//
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000358// We walk recursively the forest of bands to combine the schedules of the
359// individual bands to the overall schedule. In case tiling is requested,
360// the individual bands are tiled.
361static isl_union_map *getScheduleForBandList(isl_band_list *BandList) {
362 int NumBands;
363 isl_union_map *Schedule;
364 isl_ctx *ctx;
Tobias Grosserde68cc92011-06-30 20:01:02 +0000365
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000366 ctx = isl_band_list_get_ctx(BandList);
367 NumBands = isl_band_list_n_band(BandList);
Tobias Grosser62872012011-11-17 12:56:04 +0000368 Schedule = isl_union_map_empty(isl_space_params_alloc(ctx, 0));
Tobias Grosserde68cc92011-06-30 20:01:02 +0000369
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000370 for (int i = 0; i < NumBands; i++) {
371 isl_band *Band;
372 isl_union_map *PartialSchedule;
373 int ScheduleDimensions;
374 isl_space *Space;
Tobias Grosser44f19ac2011-07-05 22:15:53 +0000375
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000376 Band = isl_band_list_get_band(BandList, i);
Tobias Grosserb6033392011-12-08 13:02:58 +0000377 PartialSchedule = getScheduleForBand(Band, &ScheduleDimensions);
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000378 Space = isl_union_map_get_space(PartialSchedule);
Tobias Grosserde68cc92011-06-30 20:01:02 +0000379
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000380 if (isl_band_has_children(Band)) {
381 isl_band_list *Children;
382 isl_union_map *SuffixSchedule;
383
384 Children = isl_band_get_children(Band);
385 SuffixSchedule = getScheduleForBandList(Children);
386 PartialSchedule = isl_union_map_flat_range_product(PartialSchedule,
387 SuffixSchedule);
388 isl_band_list_free(Children);
Tobias Grosser67707b72011-10-23 20:59:40 +0000389 } else if (EnablePollyVector) {
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000390 for (int i = ScheduleDimensions - 1 ; i >= 0 ; i--) {
391 if (isl_band_member_is_zero_distance(Band, i)) {
392 isl_map *TileMap;
393 isl_union_map *TileUMap;
Tobias Grosserc6699b72011-06-30 20:29:13 +0000394
Tobias Grosserb6033392011-12-08 13:02:58 +0000395 TileMap = getPrevectorMap(ctx, i, ScheduleDimensions);
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000396 TileUMap = isl_union_map_from_map(TileMap);
397 TileUMap = isl_union_map_align_params(TileUMap,
398 isl_space_copy(Space));
399 PartialSchedule = isl_union_map_apply_range(PartialSchedule,
400 TileUMap);
Tobias Grosser7c5ba832011-06-30 20:29:20 +0000401 break;
402 }
403 }
Tobias Grosserde68cc92011-06-30 20:01:02 +0000404 }
405
Tobias Grosser62872012011-11-17 12:56:04 +0000406 Schedule = isl_union_map_union(Schedule, PartialSchedule);
Tobias Grosserde68cc92011-06-30 20:01:02 +0000407
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000408 isl_band_free(Band);
Tobias Grosserf5338802011-10-06 00:03:35 +0000409 isl_space_free(Space);
Tobias Grosserde68cc92011-06-30 20:01:02 +0000410 }
411
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000412 return Schedule;
Tobias Grosserde68cc92011-06-30 20:01:02 +0000413}
414
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000415static isl_union_map *getScheduleMap(isl_schedule *Schedule) {
416 isl_band_list *BandList = isl_schedule_get_band_forest(Schedule);
417 isl_union_map *ScheduleMap = getScheduleForBandList(BandList);
418 isl_band_list_free(BandList);
419 return ScheduleMap;
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000420}
421
Tobias Grosser73600b82011-10-08 00:30:40 +0000422bool IslScheduleOptimizer::runOnScop(Scop &S) {
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000423 Dependences *D = &getAnalysis<Dependences>();
424
425 // Build input data.
Tobias Grosser00383a72012-02-14 14:02:44 +0000426 int ValidityKinds = Dependences::TYPE_RAW | Dependences::TYPE_WAR
427 | Dependences::TYPE_WAW;
Tobias Grosser1deda292012-02-14 14:02:48 +0000428 int ProximityKinds;
429
430 if (OptimizeDeps == "all")
431 ProximityKinds = Dependences::TYPE_RAW | Dependences::TYPE_WAR
432 | Dependences::TYPE_WAW;
433 else if (OptimizeDeps == "raw")
Tobias Grosser1e03ad72012-02-15 09:58:42 +0000434 ProximityKinds = Dependences::TYPE_RAW;
Tobias Grosser1deda292012-02-14 14:02:48 +0000435 else {
436 errs() << "Do not know how to optimize for '" << OptimizeDeps << "'"
437 << " Falling back to optimizing all dependences.\n";
438 ProximityKinds = Dependences::TYPE_RAW | Dependences::TYPE_WAR
439 | Dependences::TYPE_WAW;
440
441 }
442
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000443
Tobias Grosser00383a72012-02-14 14:02:44 +0000444 isl_union_map *Validity = D->getDependences(ValidityKinds);
445 isl_union_map *Proximity = D->getDependences(ProximityKinds);
Tobias Grosser5f9a7622012-02-14 14:02:40 +0000446 isl_union_set *Domain = S.getDomains();
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000447
Tobias Grosser98610ee2012-02-13 23:31:39 +0000448 if (!Domain)
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000449 return false;
450
Tobias Grossera26db472012-01-30 19:38:43 +0000451 // Simplify the dependences by removing the constraints introduced by the
452 // domains. This can speed up the scheduling time significantly, as large
453 // constant coefficients will be removed from the dependences. The
454 // introduction of some additional dependences reduces the possible
455 // transformations, but in most cases, such transformation do not seem to be
456 // interesting anyway. In some cases this option may stop the scheduler to
457 // find any schedule.
458 if (SimplifyDeps == "yes") {
Tobias Grosser00383a72012-02-14 14:02:44 +0000459 Validity = isl_union_map_gist_domain(Validity, isl_union_set_copy(Domain));
460 Validity = isl_union_map_gist_range(Validity, isl_union_set_copy(Domain));
461 Proximity = isl_union_map_gist_domain(Proximity,
462 isl_union_set_copy(Domain));
463 Proximity = isl_union_map_gist_range(Proximity, isl_union_set_copy(Domain));
Tobias Grossera26db472012-01-30 19:38:43 +0000464 } else if (SimplifyDeps != "no") {
465 errs() << "warning: Option -polly-opt-simplify-deps should either be 'yes' "
466 "or 'no'. Falling back to default: 'yes'\n";
467 }
468
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000469 DEBUG(dbgs() << "\n\nCompute schedule from: ");
Tobias Grosser98610ee2012-02-13 23:31:39 +0000470 DEBUG(dbgs() << "Domain := "; isl_union_set_dump(Domain); dbgs() << ";\n");
471 DEBUG(dbgs() << "Proximity := "; isl_union_map_dump(Proximity);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000472 dbgs() << ";\n");
Tobias Grosser98610ee2012-02-13 23:31:39 +0000473 DEBUG(dbgs() << "Validity := "; isl_union_map_dump(Validity);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000474 dbgs() << ";\n");
475
Tobias Grosserb3ad85b2012-01-30 19:38:50 +0000476 int IslFusionStrategy;
477
478 if (FusionStrategy == "max") {
479 IslFusionStrategy = ISL_SCHEDULE_FUSE_MAX;
480 } else if (FusionStrategy == "min") {
481 IslFusionStrategy = ISL_SCHEDULE_FUSE_MIN;
482 } else {
483 errs() << "warning: Unknown fusion strategy. Falling back to maximal "
484 "fusion.\n";
485 IslFusionStrategy = ISL_SCHEDULE_FUSE_MAX;
486 }
487
Tobias Grosser95e860c2012-01-30 19:38:54 +0000488 int IslMaximizeBands;
489
Tobias Grossera4ea90b2012-01-30 22:43:56 +0000490 if (MaximizeBandDepth == "yes") {
Tobias Grosser95e860c2012-01-30 19:38:54 +0000491 IslMaximizeBands = 1;
Tobias Grossera4ea90b2012-01-30 22:43:56 +0000492 } else if (MaximizeBandDepth == "no") {
Tobias Grosser95e860c2012-01-30 19:38:54 +0000493 IslMaximizeBands = 0;
494 } else {
495 errs() << "warning: Option -polly-opt-maximize-bands should either be 'yes'"
496 " or 'no'. Falling back to default: 'yes'\n";
497 IslMaximizeBands = 1;
498 }
499
Tobias Grosserb3ad85b2012-01-30 19:38:50 +0000500 isl_options_set_schedule_fuse(S.getIslCtx(), IslFusionStrategy);
Tobias Grosser95e860c2012-01-30 19:38:54 +0000501 isl_options_set_schedule_maximize_band_depth(S.getIslCtx(), IslMaximizeBands);
Tobias Grosser42152ff2012-01-30 19:38:47 +0000502
503 isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_CONTINUE);
Tobias Grosser00383a72012-02-14 14:02:44 +0000504 isl_schedule *Schedule;
Tobias Grosser98610ee2012-02-13 23:31:39 +0000505 Schedule = isl_union_set_compute_schedule(Domain, Validity, Proximity);
Tobias Grosser42152ff2012-01-30 19:38:47 +0000506 isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_ABORT);
507
508 // In cases the scheduler is not able to optimize the code, we just do not
509 // touch the schedule.
Tobias Grosser98610ee2012-02-13 23:31:39 +0000510 if (!Schedule)
Tobias Grosser42152ff2012-01-30 19:38:47 +0000511 return false;
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000512
Tobias Grosser98610ee2012-02-13 23:31:39 +0000513 isl_union_map *ScheduleMap = getScheduleMap(Schedule);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000514
Tobias Grosserde68cc92011-06-30 20:01:02 +0000515 for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) {
Tobias Grosser98610ee2012-02-13 23:31:39 +0000516 ScopStmt *Stmt = *SI;
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000517
Tobias Grosser98610ee2012-02-13 23:31:39 +0000518 if (Stmt->isFinalRead())
Tobias Grosserde68cc92011-06-30 20:01:02 +0000519 continue;
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000520
Tobias Grosser98610ee2012-02-13 23:31:39 +0000521 isl_set *Domain = Stmt->getDomain();
522 isl_union_map *StmtBand;
523 StmtBand = isl_union_map_intersect_domain(isl_union_map_copy(ScheduleMap),
524 isl_union_set_from_set(Domain));
525 isl_map *StmtSchedule;
526 isl_union_map_foreach_map(StmtBand, getSingleMap, &StmtSchedule);
527 Stmt->setScattering(StmtSchedule);
528 isl_union_map_free(StmtBand);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000529 }
530
Tobias Grosser1ae9a602011-11-17 12:56:03 +0000531 isl_union_map_free(ScheduleMap);
Tobias Grosser98610ee2012-02-13 23:31:39 +0000532 isl_schedule_free(Schedule);
Tobias Grosserde68cc92011-06-30 20:01:02 +0000533
Tobias Grosser98610ee2012-02-13 23:31:39 +0000534 unsigned MaxScatDims = 0;
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000535
536 for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI)
Tobias Grosser98610ee2012-02-13 23:31:39 +0000537 MaxScatDims = std::max((*SI)->getNumScattering(), MaxScatDims);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000538
Tobias Grosser98610ee2012-02-13 23:31:39 +0000539 extendScattering(S, MaxScatDims);
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000540 return false;
541}
542
Tobias Grosser73600b82011-10-08 00:30:40 +0000543void IslScheduleOptimizer::printScop(raw_ostream &OS) const {
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000544}
545
Tobias Grosser73600b82011-10-08 00:30:40 +0000546void IslScheduleOptimizer::getAnalysisUsage(AnalysisUsage &AU) const {
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000547 ScopPass::getAnalysisUsage(AU);
548 AU.addRequired<Dependences>();
549}
550
Tobias Grosser4dca4392011-11-22 19:40:19 +0000551INITIALIZE_PASS_BEGIN(IslScheduleOptimizer, "polly-opt-isl",
Tobias Grosser73600b82011-10-08 00:30:40 +0000552 "Polly - Optimize schedule of SCoP", false, false)
553INITIALIZE_PASS_DEPENDENCY(Dependences)
554INITIALIZE_PASS_DEPENDENCY(ScopInfo)
Tobias Grosser4dca4392011-11-22 19:40:19 +0000555INITIALIZE_PASS_END(IslScheduleOptimizer, "polly-opt-isl",
Tobias Grosser73600b82011-10-08 00:30:40 +0000556 "Polly - Optimize schedule of SCoP", false, false)
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000557
Tobias Grosser73600b82011-10-08 00:30:40 +0000558Pass* polly::createIslScheduleOptimizerPass() {
559 return new IslScheduleOptimizer();
Tobias Grosser30aa24c2011-05-14 19:02:06 +0000560}