1 //===- DependenceInfo.cpp - Calculate dependency information for a Scop. --===// 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 // Calculate the data dependency relations for a Scop using ISL. 11 // 12 // The integer set library (ISL) from Sven, has a integrated dependency analysis 13 // to calculate data dependences. This pass takes advantage of this and 14 // calculate those dependences a Scop. 15 // 16 // The dependences in this pass are exact in terms that for a specific read 17 // statement instance only the last write statement instance is returned. In 18 // case of may writes a set of possible write instances is returned. This 19 // analysis will never produce redundant dependences. 20 // 21 //===----------------------------------------------------------------------===// 22 // 23 #include "polly/DependenceInfo.h" 24 #include "polly/LinkAllPasses.h" 25 #include "polly/Options.h" 26 #include "polly/ScopInfo.h" 27 #include "polly/Support/GICHelper.h" 28 #include "llvm/Support/Debug.h" 29 #include <isl/aff.h> 30 #include <isl/ctx.h> 31 #include <isl/flow.h> 32 #include <isl/map.h> 33 #include <isl/options.h> 34 #include <isl/schedule.h> 35 #include <isl/set.h> 36 #include <isl/union_map.h> 37 #include <isl/union_set.h> 38 39 using namespace polly; 40 using namespace llvm; 41 42 #define DEBUG_TYPE "polly-dependence" 43 44 static cl::opt<int> OptComputeOut( 45 "polly-dependences-computeout", 46 cl::desc("Bound the dependence analysis by a maximal amount of " 47 "computational steps (0 means no bound)"), 48 cl::Hidden, cl::init(410000), cl::ZeroOrMore, cl::cat(PollyCategory)); 49 50 static cl::opt<bool> LegalityCheckDisabled( 51 "disable-polly-legality", cl::desc("Disable polly legality check"), 52 cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory)); 53 54 enum AnalysisType { VALUE_BASED_ANALYSIS, MEMORY_BASED_ANALYSIS }; 55 56 static cl::opt<enum AnalysisType> OptAnalysisType( 57 "polly-dependences-analysis-type", 58 cl::desc("The kind of dependence analysis to use"), 59 cl::values(clEnumValN(VALUE_BASED_ANALYSIS, "value-based", 60 "Exact dependences without transitive dependences"), 61 clEnumValN(MEMORY_BASED_ANALYSIS, "memory-based", 62 "Overapproximation of dependences"), 63 clEnumValEnd), 64 cl::Hidden, cl::init(VALUE_BASED_ANALYSIS), cl::ZeroOrMore, 65 cl::cat(PollyCategory)); 66 67 //===----------------------------------------------------------------------===// 68 69 /// @brief Collect information about the SCoP @p S. 70 static void collectInfo(Scop &S, isl_union_map **Read, isl_union_map **Write, 71 isl_union_map **MayWrite, 72 isl_union_map **AccessSchedule, 73 isl_union_map **StmtSchedule) { 74 isl_space *Space = S.getParamSpace(); 75 *Read = isl_union_map_empty(isl_space_copy(Space)); 76 *Write = isl_union_map_empty(isl_space_copy(Space)); 77 *MayWrite = isl_union_map_empty(isl_space_copy(Space)); 78 *AccessSchedule = isl_union_map_empty(isl_space_copy(Space)); 79 *StmtSchedule = isl_union_map_empty(Space); 80 81 SmallPtrSet<const Value *, 8> ReductionBaseValues; 82 for (ScopStmt &Stmt : S) 83 for (MemoryAccess *MA : Stmt) 84 if (MA->isReductionLike()) 85 ReductionBaseValues.insert(MA->getBaseAddr()); 86 87 for (ScopStmt &Stmt : S) { 88 for (MemoryAccess *MA : Stmt) { 89 isl_set *domcp = Stmt.getDomain(); 90 isl_map *accdom = MA->getAccessRelation(); 91 92 accdom = isl_map_intersect_domain(accdom, domcp); 93 94 if (ReductionBaseValues.count(MA->getBaseAddr())) { 95 // Wrap the access domain and adjust the schedule accordingly. 96 // 97 // An access domain like 98 // Stmt[i0, i1] -> MemAcc_A[i0 + i1] 99 // will be transformed into 100 // [Stmt[i0, i1] -> MemAcc_A[i0 + i1]] -> MemAcc_A[i0 + i1] 101 // 102 // The original schedule looks like 103 // Stmt[i0, i1] -> [0, i0, 2, i1, 0] 104 // but as we transformed the access domain we need the schedule 105 // to match the new access domains, thus we need 106 // [Stmt[i0, i1] -> MemAcc_A[i0 + i1]] -> [0, i0, 2, i1, 0] 107 isl_map *Schedule = Stmt.getSchedule(); 108 Schedule = isl_map_apply_domain( 109 Schedule, 110 isl_map_reverse(isl_map_domain_map(isl_map_copy(accdom)))); 111 accdom = isl_map_range_map(accdom); 112 *AccessSchedule = isl_union_map_add_map(*AccessSchedule, Schedule); 113 } 114 115 if (MA->isRead()) 116 *Read = isl_union_map_add_map(*Read, accdom); 117 else 118 *Write = isl_union_map_add_map(*Write, accdom); 119 } 120 *StmtSchedule = isl_union_map_add_map(*StmtSchedule, Stmt.getSchedule()); 121 } 122 123 *StmtSchedule = 124 isl_union_map_intersect_params(*StmtSchedule, S.getAssumedContext()); 125 } 126 127 /// @brief Fix all dimension of @p Zero to 0 and add it to @p user 128 static isl_stat fixSetToZero(__isl_take isl_set *Zero, void *user) { 129 isl_union_set **User = (isl_union_set **)user; 130 for (unsigned i = 0; i < isl_set_dim(Zero, isl_dim_set); i++) 131 Zero = isl_set_fix_si(Zero, isl_dim_set, i, 0); 132 *User = isl_union_set_add_set(*User, Zero); 133 return isl_stat_ok; 134 } 135 136 /// @brief Compute the privatization dependences for a given dependency @p Map 137 /// 138 /// Privatization dependences are widened original dependences which originate 139 /// or end in a reduction access. To compute them we apply the transitive close 140 /// of the reduction dependences (which maps each iteration of a reduction 141 /// statement to all following ones) on the RAW/WAR/WAW dependences. The 142 /// dependences which start or end at a reduction statement will be extended to 143 /// depend on all following reduction statement iterations as well. 144 /// Note: "Following" here means according to the reduction dependences. 145 /// 146 /// For the input: 147 /// 148 /// S0: *sum = 0; 149 /// for (int i = 0; i < 1024; i++) 150 /// S1: *sum += i; 151 /// S2: *sum = *sum * 3; 152 /// 153 /// we have the following dependences before we add privatization dependences: 154 /// 155 /// RAW: 156 /// { S0[] -> S1[0]; S1[1023] -> S2[] } 157 /// WAR: 158 /// { } 159 /// WAW: 160 /// { S0[] -> S1[0]; S1[1024] -> S2[] } 161 /// RED: 162 /// { S1[i0] -> S1[1 + i0] : i0 >= 0 and i0 <= 1022 } 163 /// 164 /// and afterwards: 165 /// 166 /// RAW: 167 /// { S0[] -> S1[i0] : i0 >= 0 and i0 <= 1023; 168 /// S1[i0] -> S2[] : i0 >= 0 and i0 <= 1023} 169 /// WAR: 170 /// { } 171 /// WAW: 172 /// { S0[] -> S1[i0] : i0 >= 0 and i0 <= 1023; 173 /// S1[i0] -> S2[] : i0 >= 0 and i0 <= 1023} 174 /// RED: 175 /// { S1[i0] -> S1[1 + i0] : i0 >= 0 and i0 <= 1022 } 176 /// 177 /// Note: This function also computes the (reverse) transitive closure of the 178 /// reduction dependences. 179 void Dependences::addPrivatizationDependences() { 180 isl_union_map *PrivRAW, *PrivWAW, *PrivWAR; 181 182 // The transitive closure might be over approximated, thus could lead to 183 // dependency cycles in the privatization dependences. To make sure this 184 // will not happen we remove all negative dependences after we computed 185 // the transitive closure. 186 TC_RED = isl_union_map_transitive_closure(isl_union_map_copy(RED), 0); 187 188 // FIXME: Apply the current schedule instead of assuming the identity schedule 189 // here. The current approach is only valid as long as we compute the 190 // dependences only with the initial (identity schedule). Any other 191 // schedule could change "the direction of the backward dependences" we 192 // want to eliminate here. 193 isl_union_set *UDeltas = isl_union_map_deltas(isl_union_map_copy(TC_RED)); 194 isl_union_set *Universe = isl_union_set_universe(isl_union_set_copy(UDeltas)); 195 isl_union_set *Zero = isl_union_set_empty(isl_union_set_get_space(Universe)); 196 isl_union_set_foreach_set(Universe, fixSetToZero, &Zero); 197 isl_union_map *NonPositive = isl_union_set_lex_le_union_set(UDeltas, Zero); 198 199 TC_RED = isl_union_map_subtract(TC_RED, NonPositive); 200 201 TC_RED = isl_union_map_union( 202 TC_RED, isl_union_map_reverse(isl_union_map_copy(TC_RED))); 203 TC_RED = isl_union_map_coalesce(TC_RED); 204 205 isl_union_map **Maps[] = {&RAW, &WAW, &WAR}; 206 isl_union_map **PrivMaps[] = {&PrivRAW, &PrivWAW, &PrivWAR}; 207 for (unsigned u = 0; u < 3; u++) { 208 isl_union_map **Map = Maps[u], **PrivMap = PrivMaps[u]; 209 210 *PrivMap = isl_union_map_apply_range(isl_union_map_copy(*Map), 211 isl_union_map_copy(TC_RED)); 212 *PrivMap = isl_union_map_union( 213 *PrivMap, isl_union_map_apply_range(isl_union_map_copy(TC_RED), 214 isl_union_map_copy(*Map))); 215 216 *Map = isl_union_map_union(*Map, *PrivMap); 217 } 218 219 isl_union_set_free(Universe); 220 } 221 222 void Dependences::calculateDependences(Scop &S) { 223 isl_union_map *Read, *Write, *MayWrite, *AccessSchedule, *StmtSchedule, 224 *ScheduleMap; 225 226 DEBUG(dbgs() << "Scop: \n" << S << "\n"); 227 228 collectInfo(S, &Read, &Write, &MayWrite, &AccessSchedule, &StmtSchedule); 229 230 ScheduleMap = 231 isl_union_map_union(AccessSchedule, isl_union_map_copy(StmtSchedule)); 232 233 Read = isl_union_map_coalesce(Read); 234 Write = isl_union_map_coalesce(Write); 235 MayWrite = isl_union_map_coalesce(MayWrite); 236 237 long MaxOpsOld = isl_ctx_get_max_operations(S.getIslCtx()); 238 if (OptComputeOut) 239 isl_ctx_set_max_operations(S.getIslCtx(), OptComputeOut); 240 isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_CONTINUE); 241 242 DEBUG(dbgs() << "Read: " << Read << "\n"; 243 dbgs() << "Write: " << Write << "\n"; 244 dbgs() << "MayWrite: " << MayWrite << "\n"; 245 dbgs() << "Schedule: " << ScheduleMap << "\n"); 246 247 RAW = WAW = WAR = RED = nullptr; 248 249 auto *Schedule = isl_schedule_from_domain( 250 isl_union_map_domain(isl_union_map_copy(ScheduleMap))); 251 Schedule = isl_schedule_insert_partial_schedule( 252 Schedule, isl_multi_union_pw_aff_from_union_map(ScheduleMap)); 253 254 if (OptAnalysisType == VALUE_BASED_ANALYSIS) { 255 isl_union_access_info *AI; 256 isl_union_flow *Flow; 257 258 AI = isl_union_access_info_from_sink(isl_union_map_copy(Read)); 259 AI = isl_union_access_info_set_must_source(AI, isl_union_map_copy(Write)); 260 AI = isl_union_access_info_set_may_source(AI, isl_union_map_copy(MayWrite)); 261 AI = isl_union_access_info_set_schedule(AI, isl_schedule_copy(Schedule)); 262 Flow = isl_union_access_info_compute_flow(AI); 263 264 RAW = isl_union_flow_get_must_dependence(Flow); 265 isl_union_flow_free(Flow); 266 267 AI = isl_union_access_info_from_sink(isl_union_map_copy(Write)); 268 AI = isl_union_access_info_set_must_source(AI, isl_union_map_copy(Write)); 269 AI = isl_union_access_info_set_may_source(AI, isl_union_map_copy(Read)); 270 AI = isl_union_access_info_set_schedule(AI, Schedule); 271 Flow = isl_union_access_info_compute_flow(AI); 272 273 WAW = isl_union_flow_get_must_dependence(Flow); 274 WAR = isl_union_flow_get_may_dependence(Flow); 275 276 // This subtraction is needed to obtain the same results as were given by 277 // isl_union_map_compute_flow. For large sets this may add some compile-time 278 // cost. As there does not seem to be a need to distinguish between WAW and 279 // WAR, refactoring Polly to only track general non-flow dependences may 280 // improve performance. 281 WAR = isl_union_map_subtract(WAR, isl_union_map_copy(WAW)); 282 isl_union_flow_free(Flow); 283 } else { 284 isl_union_access_info *AI; 285 isl_union_flow *Flow; 286 287 Write = isl_union_map_union(Write, isl_union_map_copy(MayWrite)); 288 289 AI = isl_union_access_info_from_sink(isl_union_map_copy(Read)); 290 AI = isl_union_access_info_set_may_source(AI, isl_union_map_copy(Write)); 291 AI = isl_union_access_info_set_schedule(AI, isl_schedule_copy(Schedule)); 292 Flow = isl_union_access_info_compute_flow(AI); 293 294 RAW = isl_union_flow_get_may_dependence(Flow); 295 isl_union_flow_free(Flow); 296 297 AI = isl_union_access_info_from_sink(isl_union_map_copy(Write)); 298 AI = isl_union_access_info_set_may_source(AI, isl_union_map_copy(Read)); 299 AI = isl_union_access_info_set_schedule(AI, isl_schedule_copy(Schedule)); 300 Flow = isl_union_access_info_compute_flow(AI); 301 302 WAR = isl_union_flow_get_may_dependence(Flow); 303 isl_union_flow_free(Flow); 304 305 AI = isl_union_access_info_from_sink(isl_union_map_copy(Write)); 306 AI = isl_union_access_info_set_may_source(AI, isl_union_map_copy(Write)); 307 AI = isl_union_access_info_set_schedule(AI, Schedule); 308 Flow = isl_union_access_info_compute_flow(AI); 309 310 WAW = isl_union_flow_get_may_dependence(Flow); 311 isl_union_flow_free(Flow); 312 } 313 314 isl_union_map_free(MayWrite); 315 isl_union_map_free(Write); 316 isl_union_map_free(Read); 317 318 RAW = isl_union_map_coalesce(RAW); 319 WAW = isl_union_map_coalesce(WAW); 320 WAR = isl_union_map_coalesce(WAR); 321 322 if (isl_ctx_last_error(S.getIslCtx()) == isl_error_quota) { 323 isl_union_map_free(RAW); 324 isl_union_map_free(WAW); 325 isl_union_map_free(WAR); 326 RAW = WAW = WAR = nullptr; 327 isl_ctx_reset_error(S.getIslCtx()); 328 } 329 isl_options_set_on_error(S.getIslCtx(), ISL_ON_ERROR_ABORT); 330 isl_ctx_reset_operations(S.getIslCtx()); 331 isl_ctx_set_max_operations(S.getIslCtx(), MaxOpsOld); 332 333 isl_union_map *STMT_RAW, *STMT_WAW, *STMT_WAR; 334 STMT_RAW = isl_union_map_intersect_domain( 335 isl_union_map_copy(RAW), 336 isl_union_map_domain(isl_union_map_copy(StmtSchedule))); 337 STMT_WAW = isl_union_map_intersect_domain( 338 isl_union_map_copy(WAW), 339 isl_union_map_domain(isl_union_map_copy(StmtSchedule))); 340 STMT_WAR = isl_union_map_intersect_domain(isl_union_map_copy(WAR), 341 isl_union_map_domain(StmtSchedule)); 342 DEBUG({ 343 dbgs() << "Wrapped Dependences:\n"; 344 dump(); 345 dbgs() << "\n"; 346 }); 347 348 // To handle reduction dependences we proceed as follows: 349 // 1) Aggregate all possible reduction dependences, namely all self 350 // dependences on reduction like statements. 351 // 2) Intersect them with the actual RAW & WAW dependences to the get the 352 // actual reduction dependences. This will ensure the load/store memory 353 // addresses were __identical__ in the two iterations of the statement. 354 // 3) Relax the original RAW and WAW dependences by subtracting the actual 355 // reduction dependences. Binary reductions (sum += A[i]) cause both, and 356 // the same, RAW and WAW dependences. 357 // 4) Add the privatization dependences which are widened versions of 358 // already present dependences. They model the effect of manual 359 // privatization at the outermost possible place (namely after the last 360 // write and before the first access to a reduction location). 361 362 // Step 1) 363 RED = isl_union_map_empty(isl_union_map_get_space(RAW)); 364 for (ScopStmt &Stmt : S) { 365 for (MemoryAccess *MA : Stmt) { 366 if (!MA->isReductionLike()) 367 continue; 368 isl_set *AccDomW = isl_map_wrap(MA->getAccessRelation()); 369 isl_map *Identity = 370 isl_map_from_domain_and_range(isl_set_copy(AccDomW), AccDomW); 371 RED = isl_union_map_add_map(RED, Identity); 372 } 373 } 374 375 // Step 2) 376 RED = isl_union_map_intersect(RED, isl_union_map_copy(RAW)); 377 RED = isl_union_map_intersect(RED, isl_union_map_copy(WAW)); 378 379 if (!isl_union_map_is_empty(RED)) { 380 381 // Step 3) 382 RAW = isl_union_map_subtract(RAW, isl_union_map_copy(RED)); 383 WAW = isl_union_map_subtract(WAW, isl_union_map_copy(RED)); 384 385 // Step 4) 386 addPrivatizationDependences(); 387 } 388 389 DEBUG({ 390 dbgs() << "Final Wrapped Dependences:\n"; 391 dump(); 392 dbgs() << "\n"; 393 }); 394 395 // RED_SIN is used to collect all reduction dependences again after we 396 // split them according to the causing memory accesses. The current assumption 397 // is that our method of splitting will not have any leftovers. In the end 398 // we validate this assumption until we have more confidence in this method. 399 isl_union_map *RED_SIN = isl_union_map_empty(isl_union_map_get_space(RAW)); 400 401 // For each reduction like memory access, check if there are reduction 402 // dependences with the access relation of the memory access as a domain 403 // (wrapped space!). If so these dependences are caused by this memory access. 404 // We then move this portion of reduction dependences back to the statement -> 405 // statement space and add a mapping from the memory access to these 406 // dependences. 407 for (ScopStmt &Stmt : S) { 408 for (MemoryAccess *MA : Stmt) { 409 if (!MA->isReductionLike()) 410 continue; 411 412 isl_set *AccDomW = isl_map_wrap(MA->getAccessRelation()); 413 isl_union_map *AccRedDepU = isl_union_map_intersect_domain( 414 isl_union_map_copy(TC_RED), isl_union_set_from_set(AccDomW)); 415 if (isl_union_map_is_empty(AccRedDepU) && !isl_union_map_free(AccRedDepU)) 416 continue; 417 418 isl_map *AccRedDep = isl_map_from_union_map(AccRedDepU); 419 RED_SIN = isl_union_map_add_map(RED_SIN, isl_map_copy(AccRedDep)); 420 AccRedDep = isl_map_zip(AccRedDep); 421 AccRedDep = isl_set_unwrap(isl_map_domain(AccRedDep)); 422 setReductionDependences(MA, AccRedDep); 423 } 424 } 425 426 assert(isl_union_map_is_equal(RED_SIN, TC_RED) && 427 "Intersecting the reduction dependence domain with the wrapped access " 428 "relation is not enough, we need to loosen the access relation also"); 429 isl_union_map_free(RED_SIN); 430 431 RAW = isl_union_map_zip(RAW); 432 WAW = isl_union_map_zip(WAW); 433 WAR = isl_union_map_zip(WAR); 434 RED = isl_union_map_zip(RED); 435 TC_RED = isl_union_map_zip(TC_RED); 436 437 DEBUG({ 438 dbgs() << "Zipped Dependences:\n"; 439 dump(); 440 dbgs() << "\n"; 441 }); 442 443 RAW = isl_union_set_unwrap(isl_union_map_domain(RAW)); 444 WAW = isl_union_set_unwrap(isl_union_map_domain(WAW)); 445 WAR = isl_union_set_unwrap(isl_union_map_domain(WAR)); 446 RED = isl_union_set_unwrap(isl_union_map_domain(RED)); 447 TC_RED = isl_union_set_unwrap(isl_union_map_domain(TC_RED)); 448 449 DEBUG({ 450 dbgs() << "Unwrapped Dependences:\n"; 451 dump(); 452 dbgs() << "\n"; 453 }); 454 455 RAW = isl_union_map_union(RAW, STMT_RAW); 456 WAW = isl_union_map_union(WAW, STMT_WAW); 457 WAR = isl_union_map_union(WAR, STMT_WAR); 458 459 RAW = isl_union_map_coalesce(RAW); 460 WAW = isl_union_map_coalesce(WAW); 461 WAR = isl_union_map_coalesce(WAR); 462 RED = isl_union_map_coalesce(RED); 463 TC_RED = isl_union_map_coalesce(TC_RED); 464 465 DEBUG(dump()); 466 } 467 468 bool Dependences::isValidSchedule(Scop &S, 469 StatementToIslMapTy *NewSchedule) const { 470 if (LegalityCheckDisabled) 471 return true; 472 473 isl_union_map *Dependences = getDependences(TYPE_RAW | TYPE_WAW | TYPE_WAR); 474 isl_space *Space = S.getParamSpace(); 475 isl_union_map *Schedule = isl_union_map_empty(Space); 476 477 isl_space *ScheduleSpace = nullptr; 478 479 for (ScopStmt &Stmt : S) { 480 isl_map *StmtScat; 481 482 if (NewSchedule->find(&Stmt) == NewSchedule->end()) 483 StmtScat = Stmt.getSchedule(); 484 else 485 StmtScat = isl_map_copy((*NewSchedule)[&Stmt]); 486 487 if (!ScheduleSpace) 488 ScheduleSpace = isl_space_range(isl_map_get_space(StmtScat)); 489 490 Schedule = isl_union_map_add_map(Schedule, StmtScat); 491 } 492 493 Dependences = 494 isl_union_map_apply_domain(Dependences, isl_union_map_copy(Schedule)); 495 Dependences = isl_union_map_apply_range(Dependences, Schedule); 496 497 isl_set *Zero = isl_set_universe(isl_space_copy(ScheduleSpace)); 498 for (unsigned i = 0; i < isl_set_dim(Zero, isl_dim_set); i++) 499 Zero = isl_set_fix_si(Zero, isl_dim_set, i, 0); 500 501 isl_union_set *UDeltas = isl_union_map_deltas(Dependences); 502 isl_set *Deltas = isl_union_set_extract_set(UDeltas, ScheduleSpace); 503 isl_union_set_free(UDeltas); 504 505 isl_map *NonPositive = isl_set_lex_le_set(Deltas, Zero); 506 bool IsValid = isl_map_is_empty(NonPositive); 507 isl_map_free(NonPositive); 508 509 return IsValid; 510 } 511 512 // Check if the current scheduling dimension is parallel. 513 // 514 // We check for parallelism by verifying that the loop does not carry any 515 // dependences. 516 // 517 // Parallelism test: if the distance is zero in all outer dimensions, then it 518 // has to be zero in the current dimension as well. 519 // 520 // Implementation: first, translate dependences into time space, then force 521 // outer dimensions to be equal. If the distance is zero in the current 522 // dimension, then the loop is parallel. The distance is zero in the current 523 // dimension if it is a subset of a map with equal values for the current 524 // dimension. 525 bool Dependences::isParallel(isl_union_map *Schedule, isl_union_map *Deps, 526 isl_pw_aff **MinDistancePtr) const { 527 isl_set *Deltas, *Distance; 528 isl_map *ScheduleDeps; 529 unsigned Dimension; 530 bool IsParallel; 531 532 Deps = isl_union_map_apply_range(Deps, isl_union_map_copy(Schedule)); 533 Deps = isl_union_map_apply_domain(Deps, isl_union_map_copy(Schedule)); 534 535 if (isl_union_map_is_empty(Deps)) { 536 isl_union_map_free(Deps); 537 return true; 538 } 539 540 ScheduleDeps = isl_map_from_union_map(Deps); 541 Dimension = isl_map_dim(ScheduleDeps, isl_dim_out) - 1; 542 543 for (unsigned i = 0; i < Dimension; i++) 544 ScheduleDeps = isl_map_equate(ScheduleDeps, isl_dim_out, i, isl_dim_in, i); 545 546 Deltas = isl_map_deltas(ScheduleDeps); 547 Distance = isl_set_universe(isl_set_get_space(Deltas)); 548 549 // [0, ..., 0, +] - All zeros and last dimension larger than zero 550 for (unsigned i = 0; i < Dimension; i++) 551 Distance = isl_set_fix_si(Distance, isl_dim_set, i, 0); 552 553 Distance = isl_set_lower_bound_si(Distance, isl_dim_set, Dimension, 1); 554 Distance = isl_set_intersect(Distance, Deltas); 555 556 IsParallel = isl_set_is_empty(Distance); 557 if (IsParallel || !MinDistancePtr) { 558 isl_set_free(Distance); 559 return IsParallel; 560 } 561 562 Distance = isl_set_project_out(Distance, isl_dim_set, 0, Dimension); 563 Distance = isl_set_coalesce(Distance); 564 565 // This last step will compute a expression for the minimal value in the 566 // distance polyhedron Distance with regards to the first (outer most) 567 // dimension. 568 *MinDistancePtr = isl_pw_aff_coalesce(isl_set_dim_min(Distance, 0)); 569 570 return false; 571 } 572 573 static void printDependencyMap(raw_ostream &OS, __isl_keep isl_union_map *DM) { 574 if (DM) 575 OS << DM << "\n"; 576 else 577 OS << "n/a\n"; 578 } 579 580 void Dependences::print(raw_ostream &OS) const { 581 OS << "\tRAW dependences:\n\t\t"; 582 printDependencyMap(OS, RAW); 583 OS << "\tWAR dependences:\n\t\t"; 584 printDependencyMap(OS, WAR); 585 OS << "\tWAW dependences:\n\t\t"; 586 printDependencyMap(OS, WAW); 587 OS << "\tReduction dependences:\n\t\t"; 588 printDependencyMap(OS, RED); 589 OS << "\tTransitive closure of reduction dependences:\n\t\t"; 590 printDependencyMap(OS, TC_RED); 591 } 592 593 void Dependences::dump() const { print(dbgs()); } 594 595 void Dependences::releaseMemory() { 596 isl_union_map_free(RAW); 597 isl_union_map_free(WAR); 598 isl_union_map_free(WAW); 599 isl_union_map_free(RED); 600 isl_union_map_free(TC_RED); 601 602 RED = RAW = WAR = WAW = TC_RED = nullptr; 603 604 for (auto &ReductionDeps : ReductionDependences) 605 isl_map_free(ReductionDeps.second); 606 ReductionDependences.clear(); 607 } 608 609 isl_union_map *Dependences::getDependences(int Kinds) const { 610 assert(hasValidDependences() && "No valid dependences available"); 611 isl_space *Space = isl_union_map_get_space(RAW); 612 isl_union_map *Deps = isl_union_map_empty(Space); 613 614 if (Kinds & TYPE_RAW) 615 Deps = isl_union_map_union(Deps, isl_union_map_copy(RAW)); 616 617 if (Kinds & TYPE_WAR) 618 Deps = isl_union_map_union(Deps, isl_union_map_copy(WAR)); 619 620 if (Kinds & TYPE_WAW) 621 Deps = isl_union_map_union(Deps, isl_union_map_copy(WAW)); 622 623 if (Kinds & TYPE_RED) 624 Deps = isl_union_map_union(Deps, isl_union_map_copy(RED)); 625 626 if (Kinds & TYPE_TC_RED) 627 Deps = isl_union_map_union(Deps, isl_union_map_copy(TC_RED)); 628 629 Deps = isl_union_map_coalesce(Deps); 630 Deps = isl_union_map_detect_equalities(Deps); 631 return Deps; 632 } 633 634 bool Dependences::hasValidDependences() const { 635 return (RAW != nullptr) && (WAR != nullptr) && (WAW != nullptr); 636 } 637 638 isl_map *Dependences::getReductionDependences(MemoryAccess *MA) const { 639 return isl_map_copy(ReductionDependences.lookup(MA)); 640 } 641 642 void Dependences::setReductionDependences(MemoryAccess *MA, isl_map *D) { 643 assert(ReductionDependences.count(MA) == 0 && 644 "Reduction dependences set twice!"); 645 ReductionDependences[MA] = D; 646 } 647 648 void DependenceInfo::recomputeDependences() { 649 releaseMemory(); 650 D.calculateDependences(*S); 651 } 652 653 bool DependenceInfo::runOnScop(Scop &ScopVar) { 654 S = &ScopVar; 655 recomputeDependences(); 656 return false; 657 } 658 659 void DependenceInfo::getAnalysisUsage(AnalysisUsage &AU) const { 660 ScopPass::getAnalysisUsage(AU); 661 } 662 663 char DependenceInfo::ID = 0; 664 665 Pass *polly::createDependenceInfoPass() { return new DependenceInfo(); } 666 667 INITIALIZE_PASS_BEGIN(DependenceInfo, "polly-dependences", 668 "Polly - Calculate dependences", false, false); 669 INITIALIZE_PASS_DEPENDENCY(ScopInfo); 670 INITIALIZE_PASS_END(DependenceInfo, "polly-dependences", 671 "Polly - Calculate dependences", false, false) 672