1 //===- 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 20 #include "polly/ScheduleOptimizer.h" 21 #include "isl/aff.h" 22 #include "isl/band.h" 23 #include "isl/constraint.h" 24 #include "isl/map.h" 25 #include "isl/options.h" 26 #include "isl/schedule.h" 27 #include "isl/space.h" 28 #include "polly/CodeGen/CodeGeneration.h" 29 #include "polly/Dependences.h" 30 #include "polly/LinkAllPasses.h" 31 #include "polly/Options.h" 32 #include "polly/ScopInfo.h" 33 #include "llvm/Support/Debug.h" 34 35 using namespace llvm; 36 using namespace polly; 37 38 #define DEBUG_TYPE "polly-opt-isl" 39 40 namespace polly { 41 bool DisablePollyTiling; 42 } 43 static cl::opt<bool, true> 44 DisableTiling("polly-no-tiling", cl::desc("Disable tiling in the scheduler"), 45 cl::location(polly::DisablePollyTiling), cl::init(false), 46 cl::ZeroOrMore, cl::cat(PollyCategory)); 47 48 static cl::opt<std::string> 49 OptimizeDeps("polly-opt-optimize-only", 50 cl::desc("Only a certain kind of dependences (all/raw)"), 51 cl::Hidden, cl::init("all"), cl::ZeroOrMore, 52 cl::cat(PollyCategory)); 53 54 static cl::opt<std::string> 55 SimplifyDeps("polly-opt-simplify-deps", 56 cl::desc("Dependences should be simplified (yes/no)"), cl::Hidden, 57 cl::init("yes"), cl::ZeroOrMore, cl::cat(PollyCategory)); 58 59 static cl::opt<int> 60 MaxConstantTerm("polly-opt-max-constant-term", 61 cl::desc("The maximal constant term allowed (-1 is unlimited)"), 62 cl::Hidden, cl::init(20), cl::ZeroOrMore, 63 cl::cat(PollyCategory)); 64 65 static cl::opt<int> 66 MaxCoefficient("polly-opt-max-coefficient", 67 cl::desc("The maximal coefficient allowed (-1 is unlimited)"), 68 cl::Hidden, cl::init(20), cl::ZeroOrMore, 69 cl::cat(PollyCategory)); 70 71 static cl::opt<std::string> 72 FusionStrategy("polly-opt-fusion", 73 cl::desc("The fusion strategy to choose (min/max)"), cl::Hidden, 74 cl::init("min"), cl::ZeroOrMore, cl::cat(PollyCategory)); 75 76 static cl::opt<std::string> 77 MaximizeBandDepth("polly-opt-maximize-bands", 78 cl::desc("Maximize the band depth (yes/no)"), cl::Hidden, 79 cl::init("yes"), cl::ZeroOrMore, cl::cat(PollyCategory)); 80 81 namespace { 82 83 class IslScheduleOptimizer : public ScopPass { 84 public: 85 static char ID; 86 explicit IslScheduleOptimizer() : ScopPass(ID) { LastSchedule = nullptr; } 87 88 ~IslScheduleOptimizer() { isl_schedule_free(LastSchedule); } 89 90 virtual bool runOnScop(Scop &S); 91 void printScop(llvm::raw_ostream &OS) const; 92 void getAnalysisUsage(AnalysisUsage &AU) const; 93 94 private: 95 isl_schedule *LastSchedule; 96 97 static void extendScattering(Scop &S, unsigned NewDimensions); 98 99 /// @brief Create a map that describes a n-dimensonal tiling. 100 /// 101 /// getTileMap creates a map from a n-dimensional scattering space into an 102 /// 2*n-dimensional scattering space. The map describes a rectangular 103 /// tiling. 104 /// 105 /// Example: 106 /// scheduleDimensions = 2, parameterDimensions = 1, tileSize = 32 107 /// 108 /// tileMap := [p0] -> {[s0, s1] -> [t0, t1, s0, s1]: 109 /// t0 % 32 = 0 and t0 <= s0 < t0 + 32 and 110 /// t1 % 32 = 0 and t1 <= s1 < t1 + 32} 111 /// 112 /// Before tiling: 113 /// 114 /// for (i = 0; i < N; i++) 115 /// for (j = 0; j < M; j++) 116 /// S(i,j) 117 /// 118 /// After tiling: 119 /// 120 /// for (t_i = 0; t_i < N; i+=32) 121 /// for (t_j = 0; t_j < M; j+=32) 122 /// for (i = t_i; i < min(t_i + 32, N); i++) | Unknown that N % 32 = 0 123 /// for (j = t_j; j < t_j + 32; j++) | Known that M % 32 = 0 124 /// S(i,j) 125 /// 126 static isl_basic_map *getTileMap(isl_ctx *ctx, int scheduleDimensions, 127 isl_space *SpaceModel, int tileSize = 32); 128 129 /// @brief Get the schedule for this band. 130 /// 131 /// Polly applies transformations like tiling on top of the isl calculated 132 /// value. This can influence the number of scheduling dimension. The 133 /// number of schedule dimensions is returned in the parameter 'Dimension'. 134 static isl_union_map *getScheduleForBand(isl_band *Band, int *Dimensions); 135 136 /// @brief Create a map that pre-vectorizes one scheduling dimension. 137 /// 138 /// getPrevectorMap creates a map that maps each input dimension to the same 139 /// output dimension, except for the dimension DimToVectorize. 140 /// DimToVectorize is strip mined by 'VectorWidth' and the newly created 141 /// point loop of DimToVectorize is moved to the innermost level. 142 /// 143 /// Example (DimToVectorize=0, ScheduleDimensions=2, VectorWidth=4): 144 /// 145 /// | Before transformation 146 /// | 147 /// | A[i,j] -> [i,j] 148 /// | 149 /// | for (i = 0; i < 128; i++) 150 /// | for (j = 0; j < 128; j++) 151 /// | A(i,j); 152 /// 153 /// Prevector map: 154 /// [i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and i = ip 155 /// 156 /// | After transformation: 157 /// | 158 /// | A[i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and i = ip 159 /// | 160 /// | for (it = 0; it < 128; it+=4) 161 /// | for (j = 0; j < 128; j++) 162 /// | for (ip = max(0,it); ip < min(128, it + 3); ip++) 163 /// | A(ip,j); 164 /// 165 /// The goal of this transformation is to create a trivially vectorizable 166 /// loop. This means a parallel loop at the innermost level that has a 167 /// constant number of iterations corresponding to the target vector width. 168 /// 169 /// This transformation creates a loop at the innermost level. The loop has 170 /// a constant number of iterations, if the number of loop iterations at 171 /// DimToVectorize can be divided by VectorWidth. The default VectorWidth is 172 /// currently constant and not yet target specific. This function does not 173 /// reason about parallelism. 174 static isl_map *getPrevectorMap(isl_ctx *ctx, int DimToVectorize, 175 int ScheduleDimensions, int VectorWidth = 4); 176 177 /// @brief Get the scheduling map for a list of bands. 178 /// 179 /// Walk recursively the forest of bands to combine the schedules of the 180 /// individual bands to the overall schedule. In case tiling is requested, 181 /// the individual bands are tiled. 182 static isl_union_map *getScheduleForBandList(isl_band_list *BandList); 183 184 static isl_union_map *getScheduleMap(isl_schedule *Schedule); 185 186 using llvm::Pass::doFinalization; 187 188 virtual bool doFinalization() { 189 isl_schedule_free(LastSchedule); 190 LastSchedule = nullptr; 191 return true; 192 } 193 }; 194 } 195 196 char IslScheduleOptimizer::ID = 0; 197 198 void IslScheduleOptimizer::extendScattering(Scop &S, unsigned NewDimensions) { 199 for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) { 200 ScopStmt *Stmt = *SI; 201 unsigned OldDimensions = Stmt->getNumScattering(); 202 isl_space *Space; 203 isl_map *Map, *New; 204 205 Space = isl_space_alloc(Stmt->getIslCtx(), 0, OldDimensions, NewDimensions); 206 Map = isl_map_universe(Space); 207 208 for (unsigned i = 0; i < OldDimensions; i++) 209 Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i); 210 211 for (unsigned i = OldDimensions; i < NewDimensions; i++) 212 Map = isl_map_fix_si(Map, isl_dim_out, i, 0); 213 214 Map = isl_map_align_params(Map, S.getParamSpace()); 215 New = isl_map_apply_range(Stmt->getScattering(), Map); 216 Stmt->setScattering(New); 217 } 218 } 219 220 isl_basic_map *IslScheduleOptimizer::getTileMap(isl_ctx *ctx, 221 int scheduleDimensions, 222 isl_space *SpaceModel, 223 int tileSize) { 224 // We construct 225 // 226 // tileMap := [p0] -> {[s0, s1] -> [t0, t1, p0, p1, a0, a1]: 227 // s0 = a0 * 32 and s0 = p0 and t0 <= p0 < t0 + 32 and 228 // s1 = a1 * 32 and s1 = p1 and t1 <= p1 < t1 + 32} 229 // 230 // and project out the auxilary dimensions a0 and a1. 231 isl_space *Space = 232 isl_space_alloc(ctx, 0, scheduleDimensions, scheduleDimensions * 3); 233 isl_basic_map *tileMap = isl_basic_map_universe(isl_space_copy(Space)); 234 235 isl_local_space *LocalSpace = isl_local_space_from_space(Space); 236 237 for (int x = 0; x < scheduleDimensions; x++) { 238 int sX = x; 239 int tX = x; 240 int pX = scheduleDimensions + x; 241 int aX = 2 * scheduleDimensions + x; 242 243 isl_constraint *c; 244 245 // sX = aX * tileSize; 246 c = isl_equality_alloc(isl_local_space_copy(LocalSpace)); 247 isl_constraint_set_coefficient_si(c, isl_dim_out, sX, 1); 248 isl_constraint_set_coefficient_si(c, isl_dim_out, aX, -tileSize); 249 tileMap = isl_basic_map_add_constraint(tileMap, c); 250 251 // pX = sX; 252 c = isl_equality_alloc(isl_local_space_copy(LocalSpace)); 253 isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1); 254 isl_constraint_set_coefficient_si(c, isl_dim_in, sX, -1); 255 tileMap = isl_basic_map_add_constraint(tileMap, c); 256 257 // tX <= pX 258 c = isl_inequality_alloc(isl_local_space_copy(LocalSpace)); 259 isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1); 260 isl_constraint_set_coefficient_si(c, isl_dim_out, tX, -1); 261 tileMap = isl_basic_map_add_constraint(tileMap, c); 262 263 // pX <= tX + (tileSize - 1) 264 c = isl_inequality_alloc(isl_local_space_copy(LocalSpace)); 265 isl_constraint_set_coefficient_si(c, isl_dim_out, tX, 1); 266 isl_constraint_set_coefficient_si(c, isl_dim_out, pX, -1); 267 isl_constraint_set_constant_si(c, tileSize - 1); 268 tileMap = isl_basic_map_add_constraint(tileMap, c); 269 } 270 271 // Project out auxilary dimensions. 272 // 273 // The auxilary dimensions are transformed into existentially quantified ones. 274 // This reduces the number of visible scattering dimensions and allows Cloog 275 // to produces better code. 276 tileMap = isl_basic_map_project_out( 277 tileMap, isl_dim_out, 2 * scheduleDimensions, scheduleDimensions); 278 isl_local_space_free(LocalSpace); 279 return tileMap; 280 } 281 282 isl_union_map *IslScheduleOptimizer::getScheduleForBand(isl_band *Band, 283 int *Dimensions) { 284 isl_union_map *PartialSchedule; 285 isl_ctx *ctx; 286 isl_space *Space; 287 isl_basic_map *TileMap; 288 isl_union_map *TileUMap; 289 290 PartialSchedule = isl_band_get_partial_schedule(Band); 291 *Dimensions = isl_band_n_member(Band); 292 293 if (DisableTiling) 294 return PartialSchedule; 295 296 // It does not make any sense to tile a band with just one dimension. 297 if (*Dimensions == 1) 298 return PartialSchedule; 299 300 ctx = isl_union_map_get_ctx(PartialSchedule); 301 Space = isl_union_map_get_space(PartialSchedule); 302 303 TileMap = getTileMap(ctx, *Dimensions, Space); 304 TileUMap = isl_union_map_from_map(isl_map_from_basic_map(TileMap)); 305 TileUMap = isl_union_map_align_params(TileUMap, Space); 306 *Dimensions = 2 * *Dimensions; 307 308 return isl_union_map_apply_range(PartialSchedule, TileUMap); 309 } 310 311 isl_map *IslScheduleOptimizer::getPrevectorMap(isl_ctx *ctx, int DimToVectorize, 312 int ScheduleDimensions, 313 int VectorWidth) { 314 isl_space *Space; 315 isl_local_space *LocalSpace, *LocalSpaceRange; 316 isl_set *Modulo; 317 isl_map *TilingMap; 318 isl_constraint *c; 319 isl_aff *Aff; 320 int PointDimension; /* ip */ 321 int TileDimension; /* it */ 322 isl_val *VectorWidthMP; 323 324 assert(0 <= DimToVectorize && DimToVectorize < ScheduleDimensions); 325 326 Space = isl_space_alloc(ctx, 0, ScheduleDimensions, ScheduleDimensions + 1); 327 TilingMap = isl_map_universe(isl_space_copy(Space)); 328 LocalSpace = isl_local_space_from_space(Space); 329 PointDimension = ScheduleDimensions; 330 TileDimension = DimToVectorize; 331 332 // Create an identity map for everything except DimToVectorize and map 333 // DimToVectorize to the point loop at the innermost dimension. 334 for (int i = 0; i < ScheduleDimensions; i++) { 335 c = isl_equality_alloc(isl_local_space_copy(LocalSpace)); 336 isl_constraint_set_coefficient_si(c, isl_dim_in, i, -1); 337 338 if (i == DimToVectorize) 339 isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, 1); 340 else 341 isl_constraint_set_coefficient_si(c, isl_dim_out, i, 1); 342 343 TilingMap = isl_map_add_constraint(TilingMap, c); 344 } 345 346 // it % 'VectorWidth' = 0 347 LocalSpaceRange = isl_local_space_range(isl_local_space_copy(LocalSpace)); 348 Aff = isl_aff_zero_on_domain(LocalSpaceRange); 349 Aff = isl_aff_set_constant_si(Aff, VectorWidth); 350 Aff = isl_aff_set_coefficient_si(Aff, isl_dim_in, TileDimension, 1); 351 VectorWidthMP = isl_val_int_from_si(ctx, VectorWidth); 352 Aff = isl_aff_mod_val(Aff, VectorWidthMP); 353 Modulo = isl_pw_aff_zero_set(isl_pw_aff_from_aff(Aff)); 354 TilingMap = isl_map_intersect_range(TilingMap, Modulo); 355 356 // it <= ip 357 c = isl_inequality_alloc(isl_local_space_copy(LocalSpace)); 358 isl_constraint_set_coefficient_si(c, isl_dim_out, TileDimension, -1); 359 isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, 1); 360 TilingMap = isl_map_add_constraint(TilingMap, c); 361 362 // ip <= it + ('VectorWidth' - 1) 363 c = isl_inequality_alloc(LocalSpace); 364 isl_constraint_set_coefficient_si(c, isl_dim_out, TileDimension, 1); 365 isl_constraint_set_coefficient_si(c, isl_dim_out, PointDimension, -1); 366 isl_constraint_set_constant_si(c, VectorWidth - 1); 367 TilingMap = isl_map_add_constraint(TilingMap, c); 368 369 return TilingMap; 370 } 371 372 isl_union_map * 373 IslScheduleOptimizer::getScheduleForBandList(isl_band_list *BandList) { 374 int NumBands; 375 isl_union_map *Schedule; 376 isl_ctx *ctx; 377 378 ctx = isl_band_list_get_ctx(BandList); 379 NumBands = isl_band_list_n_band(BandList); 380 Schedule = isl_union_map_empty(isl_space_params_alloc(ctx, 0)); 381 382 for (int i = 0; i < NumBands; i++) { 383 isl_band *Band; 384 isl_union_map *PartialSchedule; 385 int ScheduleDimensions; 386 isl_space *Space; 387 388 Band = isl_band_list_get_band(BandList, i); 389 PartialSchedule = getScheduleForBand(Band, &ScheduleDimensions); 390 Space = isl_union_map_get_space(PartialSchedule); 391 392 if (isl_band_has_children(Band)) { 393 isl_band_list *Children; 394 isl_union_map *SuffixSchedule; 395 396 Children = isl_band_get_children(Band); 397 SuffixSchedule = getScheduleForBandList(Children); 398 PartialSchedule = 399 isl_union_map_flat_range_product(PartialSchedule, SuffixSchedule); 400 isl_band_list_free(Children); 401 } else if (PollyVectorizerChoice != VECTORIZER_NONE) { 402 // In case we are at the innermost band, we try to prepare for 403 // vectorization. This means, we look for the innermost parallel loop 404 // and strip mine this loop to the innermost level using a strip-mine 405 // factor corresponding to the number of vector iterations. 406 int NumDims = isl_band_n_member(Band); 407 for (int j = NumDims - 1; j >= 0; j--) { 408 if (isl_band_member_is_coincident(Band, j)) { 409 isl_map *TileMap; 410 isl_union_map *TileUMap; 411 412 TileMap = getPrevectorMap(ctx, ScheduleDimensions - NumDims + j, 413 ScheduleDimensions); 414 TileUMap = isl_union_map_from_map(TileMap); 415 TileUMap = 416 isl_union_map_align_params(TileUMap, isl_space_copy(Space)); 417 PartialSchedule = 418 isl_union_map_apply_range(PartialSchedule, TileUMap); 419 break; 420 } 421 } 422 } 423 424 Schedule = isl_union_map_union(Schedule, PartialSchedule); 425 426 isl_band_free(Band); 427 isl_space_free(Space); 428 } 429 430 return Schedule; 431 } 432 433 isl_union_map *IslScheduleOptimizer::getScheduleMap(isl_schedule *Schedule) { 434 isl_band_list *BandList = isl_schedule_get_band_forest(Schedule); 435 isl_union_map *ScheduleMap = getScheduleForBandList(BandList); 436 isl_band_list_free(BandList); 437 return ScheduleMap; 438 } 439 440 bool IslScheduleOptimizer::runOnScop(Scop &S) { 441 Dependences *D = &getAnalysis<Dependences>(); 442 443 if (!D->hasValidDependences()) 444 return false; 445 446 isl_schedule_free(LastSchedule); 447 LastSchedule = nullptr; 448 449 // Build input data. 450 int ValidityKinds = 451 Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW; 452 int ProximityKinds; 453 454 if (OptimizeDeps == "all") 455 ProximityKinds = 456 Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW; 457 else if (OptimizeDeps == "raw") 458 ProximityKinds = Dependences::TYPE_RAW; 459 else { 460 errs() << "Do not know how to optimize for '" << OptimizeDeps << "'" 461 << " Falling back to optimizing all dependences.\n"; 462 ProximityKinds = 463 Dependences::TYPE_RAW | Dependences::TYPE_WAR | Dependences::TYPE_WAW; 464 } 465 466 isl_union_set *Domain = S.getDomains(); 467 468 if (!Domain) 469 return false; 470 471 isl_union_map *Validity = D->getDependences(ValidityKinds); 472 isl_union_map *Proximity = D->getDependences(ProximityKinds); 473 474 // Simplify the dependences by removing the constraints introduced by the 475 // domains. This can speed up the scheduling time significantly, as large 476 // constant coefficients will be removed from the dependences. The 477 // introduction of some additional dependences reduces the possible 478 // transformations, but in most cases, such transformation do not seem to be 479 // interesting anyway. In some cases this option may stop the scheduler to 480 // find any schedule. 481 if (SimplifyDeps == "yes") { 482 Validity = isl_union_map_gist_domain(Validity, isl_union_set_copy(Domain)); 483 Validity = isl_union_map_gist_range(Validity, isl_union_set_copy(Domain)); 484 Proximity = 485 isl_union_map_gist_domain(Proximity, isl_union_set_copy(Domain)); 486 Proximity = isl_union_map_gist_range(Proximity, isl_union_set_copy(Domain)); 487 } else if (SimplifyDeps != "no") { 488 errs() << "warning: Option -polly-opt-simplify-deps should either be 'yes' " 489 "or 'no'. Falling back to default: 'yes'\n"; 490 } 491 492 DEBUG(dbgs() << "\n\nCompute schedule from: "); 493 DEBUG(dbgs() << "Domain := "; isl_union_set_dump(Domain); dbgs() << ";\n"); 494 DEBUG(dbgs() << "Proximity := "; isl_union_map_dump(Proximity); 495 dbgs() << ";\n"); 496 DEBUG(dbgs() << "Validity := "; isl_union_map_dump(Validity); 497 dbgs() << ";\n"); 498 499 int IslFusionStrategy; 500 501 if (FusionStrategy == "max") { 502 IslFusionStrategy = ISL_SCHEDULE_FUSE_MAX; 503 } else if (FusionStrategy == "min") { 504 IslFusionStrategy = ISL_SCHEDULE_FUSE_MIN; 505 } else { 506 errs() << "warning: Unknown fusion strategy. Falling back to maximal " 507 "fusion.\n"; 508 IslFusionStrategy = ISL_SCHEDULE_FUSE_MAX; 509 } 510 511 int IslMaximizeBands; 512 513 if (MaximizeBandDepth == "yes") { 514 IslMaximizeBands = 1; 515 } else if (MaximizeBandDepth == "no") { 516 IslMaximizeBands = 0; 517 } else { 518 errs() << "warning: Option -polly-opt-maximize-bands should either be 'yes'" 519 " or 'no'. Falling back to default: 'yes'\n"; 520 IslMaximizeBands = 1; 521 } 522 523 isl_options_set_schedule_fuse(S.getIslCtx(), IslFusionStrategy); 524 isl_options_set_schedule_maximize_band_depth(S.getIslCtx(), IslMaximizeBands); 525 isl_options_set_schedule_max_constant_term(S.getIslCtx(), MaxConstantTerm); 526 isl_options_set_schedule_max_coefficient(S.getIslCtx(), MaxCoefficient); 527 528 isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_CONTINUE); 529 530 isl_schedule_constraints *ScheduleConstraints; 531 ScheduleConstraints = isl_schedule_constraints_on_domain(Domain); 532 ScheduleConstraints = 533 isl_schedule_constraints_set_proximity(ScheduleConstraints, Proximity); 534 ScheduleConstraints = isl_schedule_constraints_set_validity( 535 ScheduleConstraints, isl_union_map_copy(Validity)); 536 ScheduleConstraints = 537 isl_schedule_constraints_set_coincidence(ScheduleConstraints, Validity); 538 isl_schedule *Schedule; 539 Schedule = isl_schedule_constraints_compute_schedule(ScheduleConstraints); 540 isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_ABORT); 541 542 // In cases the scheduler is not able to optimize the code, we just do not 543 // touch the schedule. 544 if (!Schedule) 545 return false; 546 547 DEBUG(dbgs() << "Schedule := "; isl_schedule_dump(Schedule); dbgs() << ";\n"); 548 549 isl_union_map *ScheduleMap = getScheduleMap(Schedule); 550 551 for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) { 552 ScopStmt *Stmt = *SI; 553 isl_map *StmtSchedule; 554 isl_set *Domain = Stmt->getDomain(); 555 isl_union_map *StmtBand; 556 StmtBand = isl_union_map_intersect_domain(isl_union_map_copy(ScheduleMap), 557 isl_union_set_from_set(Domain)); 558 if (isl_union_map_is_empty(StmtBand)) { 559 StmtSchedule = isl_map_from_domain(isl_set_empty(Stmt->getDomainSpace())); 560 isl_union_map_free(StmtBand); 561 } else { 562 assert(isl_union_map_n_map(StmtBand) == 1); 563 StmtSchedule = isl_map_from_union_map(StmtBand); 564 } 565 566 Stmt->setScattering(StmtSchedule); 567 } 568 569 isl_union_map_free(ScheduleMap); 570 LastSchedule = Schedule; 571 572 unsigned MaxScatDims = 0; 573 574 for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) 575 MaxScatDims = std::max((*SI)->getNumScattering(), MaxScatDims); 576 577 extendScattering(S, MaxScatDims); 578 return false; 579 } 580 581 void IslScheduleOptimizer::printScop(raw_ostream &OS) const { 582 isl_printer *p; 583 char *ScheduleStr; 584 585 OS << "Calculated schedule:\n"; 586 587 if (!LastSchedule) { 588 OS << "n/a\n"; 589 return; 590 } 591 592 p = isl_printer_to_str(isl_schedule_get_ctx(LastSchedule)); 593 p = isl_printer_print_schedule(p, LastSchedule); 594 ScheduleStr = isl_printer_get_str(p); 595 isl_printer_free(p); 596 597 OS << ScheduleStr << "\n"; 598 } 599 600 void IslScheduleOptimizer::getAnalysisUsage(AnalysisUsage &AU) const { 601 ScopPass::getAnalysisUsage(AU); 602 AU.addRequired<Dependences>(); 603 } 604 605 Pass *polly::createIslScheduleOptimizerPass() { 606 return new IslScheduleOptimizer(); 607 } 608 609 INITIALIZE_PASS_BEGIN(IslScheduleOptimizer, "polly-opt-isl", 610 "Polly - Optimize schedule of SCoP", false, false); 611 INITIALIZE_PASS_DEPENDENCY(Dependences); 612 INITIALIZE_PASS_DEPENDENCY(ScopInfo); 613 INITIALIZE_PASS_END(IslScheduleOptimizer, "polly-opt-isl", 614 "Polly - Optimize schedule of SCoP", false, false) 615