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