Daily bump.
[official-gcc.git] / gcc / graphite-dependences.c
blobcab63478dff5f75996b4b231bea710bfd2168a3f
1 /* Data dependence analysis for Graphite.
2 Copyright (C) 2009-2014 Free Software Foundation, Inc.
3 Contributed by Sebastian Pop <sebastian.pop@amd.com> and
4 Konrad Trifunovic <konrad.trifunovic@inria.fr>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 #include "config.h"
24 #ifdef HAVE_isl
25 #include <isl/set.h>
26 #include <isl/map.h>
27 #include <isl/union_map.h>
28 #include <isl/flow.h>
29 #include <isl/constraint.h>
30 #ifdef HAVE_cloog
31 #include <cloog/cloog.h>
32 #include <cloog/isl/domain.h>
33 #endif
34 #endif
36 #include "system.h"
37 #include "coretypes.h"
38 #include "tree.h"
39 #include "basic-block.h"
40 #include "tree-ssa-alias.h"
41 #include "internal-fn.h"
42 #include "gimple-expr.h"
43 #include "is-a.h"
44 #include "gimple.h"
45 #include "gimple-iterator.h"
46 #include "tree-ssa-loop.h"
47 #include "tree-pass.h"
48 #include "cfgloop.h"
49 #include "tree-chrec.h"
50 #include "tree-data-ref.h"
51 #include "tree-scalar-evolution.h"
52 #include "sese.h"
54 #ifdef HAVE_isl
55 #include "graphite-poly.h"
56 #include "graphite-htab.h"
58 isl_union_map *
59 scop_get_dependences (scop_p scop)
61 isl_union_map *dependences;
63 if (!scop->must_raw)
64 compute_deps (scop, SCOP_BBS (scop),
65 &scop->must_raw, &scop->may_raw,
66 &scop->must_raw_no_source, &scop->may_raw_no_source,
67 &scop->must_war, &scop->may_war,
68 &scop->must_war_no_source, &scop->may_war_no_source,
69 &scop->must_waw, &scop->may_waw,
70 &scop->must_waw_no_source, &scop->may_waw_no_source);
72 dependences = isl_union_map_copy (scop->must_raw);
73 dependences = isl_union_map_union (dependences,
74 isl_union_map_copy (scop->must_war));
75 dependences = isl_union_map_union (dependences,
76 isl_union_map_copy (scop->must_waw));
77 dependences = isl_union_map_union (dependences,
78 isl_union_map_copy (scop->may_raw));
79 dependences = isl_union_map_union (dependences,
80 isl_union_map_copy (scop->may_war));
81 dependences = isl_union_map_union (dependences,
82 isl_union_map_copy (scop->may_waw));
84 return dependences;
87 /* Add the constraints from the set S to the domain of MAP. */
89 static isl_map *
90 constrain_domain (isl_map *map, isl_set *s)
92 isl_space *d = isl_map_get_space (map);
93 isl_id *id = isl_space_get_tuple_id (d, isl_dim_in);
95 s = isl_set_set_tuple_id (s, id);
96 isl_space_free (d);
97 return isl_map_intersect_domain (map, s);
100 /* Constrain pdr->accesses with pdr->extent and pbb->domain. */
102 static isl_map *
103 add_pdr_constraints (poly_dr_p pdr, poly_bb_p pbb)
105 isl_map *x = isl_map_intersect_range (isl_map_copy (pdr->accesses),
106 isl_set_copy (pdr->extent));
107 x = constrain_domain (x, isl_set_copy (pbb->domain));
108 return x;
111 /* Returns all the memory reads in SCOP. */
113 static isl_union_map *
114 scop_get_reads (scop_p scop, vec<poly_bb_p> pbbs)
116 int i, j;
117 poly_bb_p pbb;
118 poly_dr_p pdr;
119 isl_space *space = isl_set_get_space (scop->context);
120 isl_union_map *res = isl_union_map_empty (space);
122 FOR_EACH_VEC_ELT (pbbs, i, pbb)
124 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
125 if (pdr_read_p (pdr))
126 res = isl_union_map_add_map (res, add_pdr_constraints (pdr, pbb));
129 return res;
132 /* Returns all the memory must writes in SCOP. */
134 static isl_union_map *
135 scop_get_must_writes (scop_p scop, vec<poly_bb_p> pbbs)
137 int i, j;
138 poly_bb_p pbb;
139 poly_dr_p pdr;
140 isl_space *space = isl_set_get_space (scop->context);
141 isl_union_map *res = isl_union_map_empty (space);
143 FOR_EACH_VEC_ELT (pbbs, i, pbb)
145 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
146 if (pdr_write_p (pdr))
147 res = isl_union_map_add_map (res, add_pdr_constraints (pdr, pbb));
150 return res;
153 /* Returns all the memory may writes in SCOP. */
155 static isl_union_map *
156 scop_get_may_writes (scop_p scop, vec<poly_bb_p> pbbs)
158 int i, j;
159 poly_bb_p pbb;
160 poly_dr_p pdr;
161 isl_space *space = isl_set_get_space (scop->context);
162 isl_union_map *res = isl_union_map_empty (space);
164 FOR_EACH_VEC_ELT (pbbs, i, pbb)
166 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
167 if (pdr_may_write_p (pdr))
168 res = isl_union_map_add_map (res, add_pdr_constraints (pdr, pbb));
171 return res;
174 /* Returns all the original schedules in SCOP. */
176 static isl_union_map *
177 scop_get_original_schedule (scop_p scop, vec<poly_bb_p> pbbs)
179 int i;
180 poly_bb_p pbb;
181 isl_space *space = isl_set_get_space (scop->context);
182 isl_union_map *res = isl_union_map_empty (space);
184 FOR_EACH_VEC_ELT (pbbs, i, pbb)
186 res = isl_union_map_add_map
187 (res, constrain_domain (isl_map_copy (pbb->schedule),
188 isl_set_copy (pbb->domain)));
191 return res;
194 /* Returns all the transformed schedules in SCOP. */
196 static isl_union_map *
197 scop_get_transformed_schedule (scop_p scop, vec<poly_bb_p> pbbs)
199 int i;
200 poly_bb_p pbb;
201 isl_space *space = isl_set_get_space (scop->context);
202 isl_union_map *res = isl_union_map_empty (space);
204 FOR_EACH_VEC_ELT (pbbs, i, pbb)
206 res = isl_union_map_add_map
207 (res, constrain_domain (isl_map_copy (pbb->transformed),
208 isl_set_copy (pbb->domain)));
211 return res;
214 /* Helper function used on each MAP of a isl_union_map. Computes the
215 maximal output dimension. */
217 static int
218 max_number_of_out_dimensions (__isl_take isl_map *map, void *user)
220 int global_max = *((int *) user);
221 isl_space *space = isl_map_get_space (map);
222 int nb_out = isl_space_dim (space, isl_dim_out);
224 if (global_max < nb_out)
225 *((int *) user) = nb_out;
227 isl_map_free (map);
228 isl_space_free (space);
229 return 0;
232 /* Extends the output dimension of MAP to MAX dimensions. */
234 static __isl_give isl_map *
235 extend_map (__isl_take isl_map *map, int max)
237 isl_space *space = isl_map_get_space (map);
238 int n = isl_space_dim (space, isl_dim_out);
240 isl_space_free (space);
241 return isl_map_add_dims (map, isl_dim_out, max - n);
244 /* Structure used to pass parameters to extend_schedule_1. */
246 struct extend_schedule_str {
247 int max;
248 isl_union_map *umap;
251 /* Helper function for extend_schedule. */
253 static int
254 extend_schedule_1 (__isl_take isl_map *map, void *user)
256 struct extend_schedule_str *str = (struct extend_schedule_str *) user;
257 str->umap = isl_union_map_add_map (str->umap, extend_map (map, str->max));
258 return 0;
261 /* Return a relation that has uniform output dimensions. */
263 __isl_give isl_union_map *
264 extend_schedule (__isl_take isl_union_map *x)
266 int max = 0;
267 int res;
268 struct extend_schedule_str str;
270 res = isl_union_map_foreach_map (x, max_number_of_out_dimensions, (void *) &max);
271 gcc_assert (res == 0);
273 str.max = max;
274 str.umap = isl_union_map_empty (isl_union_map_get_space (x));
275 res = isl_union_map_foreach_map (x, extend_schedule_1, (void *) &str);
276 gcc_assert (res == 0);
278 isl_union_map_free (x);
279 return str.umap;
282 /* Applies SCHEDULE to the in and out dimensions of the dependences
283 DEPS and return the resulting relation. */
285 static isl_map *
286 apply_schedule_on_deps (__isl_keep isl_union_map *schedule,
287 __isl_keep isl_union_map *deps)
289 isl_map *x;
290 isl_union_map *ux, *trans;
292 trans = isl_union_map_copy (schedule);
293 trans = extend_schedule (trans);
294 ux = isl_union_map_copy (deps);
295 ux = isl_union_map_apply_domain (ux, isl_union_map_copy (trans));
296 ux = isl_union_map_apply_range (ux, trans);
297 if (isl_union_map_is_empty (ux))
299 isl_union_map_free (ux);
300 return NULL;
302 x = isl_map_from_union_map (ux);
304 return x;
307 /* Return true when SCHEDULE does not violate the data DEPS: that is
308 when the intersection of LEX with the DEPS transformed by SCHEDULE
309 is empty. LEX is the relation in which the outputs occur before
310 the inputs. */
312 static bool
313 no_violations (__isl_keep isl_union_map *schedule,
314 __isl_keep isl_union_map *deps)
316 bool res;
317 isl_space *space;
318 isl_map *lex, *x;
320 if (isl_union_map_is_empty (deps))
321 return true;
323 x = apply_schedule_on_deps (schedule, deps);
324 space = isl_map_get_space (x);
325 space = isl_space_range (space);
326 lex = isl_map_lex_ge (space);
327 x = isl_map_intersect (x, lex);
328 res = isl_map_is_empty (x);
330 isl_map_free (x);
331 return res;
334 /* Return true when DEPS is non empty and the intersection of LEX with
335 the DEPS transformed by SCHEDULE is non empty. LEX is the relation
336 in which all the inputs before DEPTH occur at the same time as the
337 output, and the input at DEPTH occurs before output. */
339 bool
340 carries_deps (__isl_keep isl_union_map *schedule,
341 __isl_keep isl_union_map *deps,
342 int depth)
344 bool res;
345 int i;
346 isl_space *space;
347 isl_map *lex, *x;
348 isl_constraint *ineq;
350 if (isl_union_map_is_empty (deps))
351 return false;
353 x = apply_schedule_on_deps (schedule, deps);
354 if (x == NULL)
355 return false;
356 space = isl_map_get_space (x);
357 space = isl_space_range (space);
358 lex = isl_map_lex_le (space);
359 space = isl_map_get_space (x);
360 ineq = isl_inequality_alloc (isl_local_space_from_space (space));
362 for (i = 0; i < depth - 1; i++)
363 lex = isl_map_equate (lex, isl_dim_in, i, isl_dim_out, i);
365 /* in + 1 <= out */
366 ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_out, depth - 1, 1);
367 ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_in, depth - 1, -1);
368 ineq = isl_constraint_set_constant_si (ineq, -1);
369 lex = isl_map_add_constraint (lex, ineq);
370 x = isl_map_intersect (x, lex);
371 res = !isl_map_is_empty (x);
373 isl_map_free (x);
374 return res;
377 /* Subtract from the RAW, WAR, and WAW dependences those relations
378 that have been marked as belonging to an associative commutative
379 reduction. */
381 static void
382 subtract_commutative_associative_deps (scop_p scop,
383 vec<poly_bb_p> pbbs,
384 isl_union_map *original,
385 isl_union_map **must_raw,
386 isl_union_map **may_raw,
387 isl_union_map **must_raw_no_source,
388 isl_union_map **may_raw_no_source,
389 isl_union_map **must_war,
390 isl_union_map **may_war,
391 isl_union_map **must_war_no_source,
392 isl_union_map **may_war_no_source,
393 isl_union_map **must_waw,
394 isl_union_map **may_waw,
395 isl_union_map **must_waw_no_source,
396 isl_union_map **may_waw_no_source)
398 int i, j;
399 poly_bb_p pbb;
400 poly_dr_p pdr;
401 isl_space *space = isl_set_get_space (scop->context);
403 FOR_EACH_VEC_ELT (pbbs, i, pbb)
404 if (PBB_IS_REDUCTION (pbb))
406 int res;
407 isl_union_map *r = isl_union_map_empty (isl_space_copy (space));
408 isl_union_map *must_w = isl_union_map_empty (isl_space_copy (space));
409 isl_union_map *may_w = isl_union_map_empty (isl_space_copy (space));
410 isl_union_map *all_w;
411 isl_union_map *empty;
412 isl_union_map *x_must_raw;
413 isl_union_map *x_may_raw;
414 isl_union_map *x_must_raw_no_source;
415 isl_union_map *x_may_raw_no_source;
416 isl_union_map *x_must_war;
417 isl_union_map *x_may_war;
418 isl_union_map *x_must_war_no_source;
419 isl_union_map *x_may_war_no_source;
420 isl_union_map *x_must_waw;
421 isl_union_map *x_may_waw;
422 isl_union_map *x_must_waw_no_source;
423 isl_union_map *x_may_waw_no_source;
425 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
426 if (pdr_read_p (pdr))
427 r = isl_union_map_add_map (r, add_pdr_constraints (pdr, pbb));
429 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
430 if (pdr_write_p (pdr))
431 must_w = isl_union_map_add_map (must_w,
432 add_pdr_constraints (pdr, pbb));
434 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
435 if (pdr_may_write_p (pdr))
436 may_w = isl_union_map_add_map (may_w,
437 add_pdr_constraints (pdr, pbb));
439 all_w = isl_union_map_union
440 (isl_union_map_copy (must_w), isl_union_map_copy (may_w));
441 empty = isl_union_map_empty (isl_union_map_get_space (all_w));
443 res = isl_union_map_compute_flow (isl_union_map_copy (r),
444 isl_union_map_copy (must_w),
445 isl_union_map_copy (may_w),
446 isl_union_map_copy (original),
447 &x_must_raw, &x_may_raw,
448 &x_must_raw_no_source,
449 &x_may_raw_no_source);
450 gcc_assert (res == 0);
451 res = isl_union_map_compute_flow (isl_union_map_copy (all_w),
452 r, empty,
453 isl_union_map_copy (original),
454 &x_must_war, &x_may_war,
455 &x_must_war_no_source,
456 &x_may_war_no_source);
457 gcc_assert (res == 0);
458 res = isl_union_map_compute_flow (all_w, must_w, may_w,
459 isl_union_map_copy (original),
460 &x_must_waw, &x_may_waw,
461 &x_must_waw_no_source,
462 &x_may_waw_no_source);
463 gcc_assert (res == 0);
465 if (must_raw)
466 *must_raw = isl_union_map_subtract (*must_raw, x_must_raw);
467 else
468 isl_union_map_free (x_must_raw);
470 if (may_raw)
471 *may_raw = isl_union_map_subtract (*may_raw, x_may_raw);
472 else
473 isl_union_map_free (x_may_raw);
475 if (must_raw_no_source)
476 *must_raw_no_source = isl_union_map_subtract (*must_raw_no_source,
477 x_must_raw_no_source);
478 else
479 isl_union_map_free (x_must_raw_no_source);
481 if (may_raw_no_source)
482 *may_raw_no_source = isl_union_map_subtract (*may_raw_no_source,
483 x_may_raw_no_source);
484 else
485 isl_union_map_free (x_may_raw_no_source);
487 if (must_war)
488 *must_war = isl_union_map_subtract (*must_war, x_must_war);
489 else
490 isl_union_map_free (x_must_war);
492 if (may_war)
493 *may_war = isl_union_map_subtract (*may_war, x_may_war);
494 else
495 isl_union_map_free (x_may_war);
497 if (must_war_no_source)
498 *must_war_no_source = isl_union_map_subtract (*must_war_no_source,
499 x_must_war_no_source);
500 else
501 isl_union_map_free (x_must_war_no_source);
503 if (may_war_no_source)
504 *may_war_no_source = isl_union_map_subtract (*may_war_no_source,
505 x_may_war_no_source);
506 else
507 isl_union_map_free (x_may_war_no_source);
509 if (must_waw)
510 *must_waw = isl_union_map_subtract (*must_waw, x_must_waw);
511 else
512 isl_union_map_free (x_must_waw);
514 if (may_waw)
515 *may_waw = isl_union_map_subtract (*may_waw, x_may_waw);
516 else
517 isl_union_map_free (x_may_waw);
519 if (must_waw_no_source)
520 *must_waw_no_source = isl_union_map_subtract (*must_waw_no_source,
521 x_must_waw_no_source);
522 else
523 isl_union_map_free (x_must_waw_no_source);
525 if (may_waw_no_source)
526 *may_waw_no_source = isl_union_map_subtract (*may_waw_no_source,
527 x_may_waw_no_source);
528 else
529 isl_union_map_free (x_may_waw_no_source);
532 isl_union_map_free (original);
533 isl_space_free (space);
536 /* Compute the original data dependences in SCOP for all the reads and
537 writes in PBBS. */
539 void
540 compute_deps (scop_p scop, vec<poly_bb_p> pbbs,
541 isl_union_map **must_raw,
542 isl_union_map **may_raw,
543 isl_union_map **must_raw_no_source,
544 isl_union_map **may_raw_no_source,
545 isl_union_map **must_war,
546 isl_union_map **may_war,
547 isl_union_map **must_war_no_source,
548 isl_union_map **may_war_no_source,
549 isl_union_map **must_waw,
550 isl_union_map **may_waw,
551 isl_union_map **must_waw_no_source,
552 isl_union_map **may_waw_no_source)
554 isl_union_map *reads = scop_get_reads (scop, pbbs);
555 isl_union_map *must_writes = scop_get_must_writes (scop, pbbs);
556 isl_union_map *may_writes = scop_get_may_writes (scop, pbbs);
557 isl_union_map *all_writes = isl_union_map_union
558 (isl_union_map_copy (must_writes), isl_union_map_copy (may_writes));
559 isl_space *space = isl_union_map_get_space (all_writes);
560 isl_union_map *empty = isl_union_map_empty (space);
561 isl_union_map *original = scop_get_original_schedule (scop, pbbs);
562 int res;
564 res = isl_union_map_compute_flow (isl_union_map_copy (reads),
565 isl_union_map_copy (must_writes),
566 isl_union_map_copy (may_writes),
567 isl_union_map_copy (original),
568 must_raw, may_raw, must_raw_no_source,
569 may_raw_no_source);
570 gcc_assert (res == 0);
571 res = isl_union_map_compute_flow (isl_union_map_copy (all_writes),
572 reads, empty,
573 isl_union_map_copy (original),
574 must_war, may_war, must_war_no_source,
575 may_war_no_source);
576 gcc_assert (res == 0);
577 res = isl_union_map_compute_flow (all_writes, must_writes, may_writes,
578 isl_union_map_copy (original),
579 must_waw, may_waw, must_waw_no_source,
580 may_waw_no_source);
581 gcc_assert (res == 0);
583 subtract_commutative_associative_deps
584 (scop, pbbs, original,
585 must_raw, may_raw, must_raw_no_source, may_raw_no_source,
586 must_war, may_war, must_war_no_source, may_war_no_source,
587 must_waw, may_waw, must_waw_no_source, may_waw_no_source);
590 /* Given a TRANSFORM, check whether it respects the original
591 dependences in SCOP. Returns true when TRANSFORM is a safe
592 transformation. */
594 static bool
595 transform_is_safe (scop_p scop, isl_union_map *transform)
597 bool res;
599 if (!scop->must_raw)
600 compute_deps (scop, SCOP_BBS (scop),
601 &scop->must_raw, &scop->may_raw,
602 &scop->must_raw_no_source, &scop->may_raw_no_source,
603 &scop->must_war, &scop->may_war,
604 &scop->must_war_no_source, &scop->may_war_no_source,
605 &scop->must_waw, &scop->may_waw,
606 &scop->must_waw_no_source, &scop->may_waw_no_source);
608 res = (no_violations (transform, scop->must_raw)
609 && no_violations (transform, scop->may_raw)
610 && no_violations (transform, scop->must_war)
611 && no_violations (transform, scop->may_war)
612 && no_violations (transform, scop->must_waw)
613 && no_violations (transform, scop->may_waw));
615 isl_union_map_free (transform);
616 return res;
619 /* Return true when the SCOP transformed schedule is correct. */
621 bool
622 graphite_legal_transform (scop_p scop)
624 int res;
625 isl_union_map *transform;
627 timevar_push (TV_GRAPHITE_DATA_DEPS);
628 transform = scop_get_transformed_schedule (scop, SCOP_BBS (scop));
629 res = transform_is_safe (scop, transform);
630 timevar_pop (TV_GRAPHITE_DATA_DEPS);
632 return res;
635 #ifdef HAVE_cloog
637 /* Return true when the loop at DEPTH carries dependences. BODY is
638 the body of the loop. */
640 static bool
641 loop_level_carries_dependences (scop_p scop, vec<poly_bb_p> body,
642 int depth)
644 isl_union_map *transform = scop_get_transformed_schedule (scop, body);
645 isl_union_map *must_raw, *may_raw;
646 isl_union_map *must_war, *may_war;
647 isl_union_map *must_waw, *may_waw;
648 int res;
650 compute_deps (scop, body,
651 &must_raw, &may_raw, NULL, NULL,
652 &must_war, &may_war, NULL, NULL,
653 &must_waw, &may_waw, NULL, NULL);
655 res = (carries_deps (transform, must_raw, depth)
656 || carries_deps (transform, may_raw, depth)
657 || carries_deps (transform, must_war, depth)
658 || carries_deps (transform, may_war, depth)
659 || carries_deps (transform, must_waw, depth)
660 || carries_deps (transform, may_waw, depth));
662 isl_union_map_free (transform);
663 isl_union_map_free (must_raw);
664 isl_union_map_free (may_raw);
665 isl_union_map_free (must_war);
666 isl_union_map_free (may_war);
667 isl_union_map_free (must_waw);
668 isl_union_map_free (may_waw);
669 return res;
672 /* Returns true when the loop L at level DEPTH is parallel.
673 BB_PBB_MAPPING is a map between a basic_block and its related
674 poly_bb_p. */
676 bool
677 loop_is_parallel_p (loop_p loop, bb_pbb_htab_type *bb_pbb_mapping, int depth)
679 bool dependences;
680 scop_p scop;
682 timevar_push (TV_GRAPHITE_DATA_DEPS);
683 auto_vec<poly_bb_p, 3> body;
684 scop = get_loop_body_pbbs (loop, bb_pbb_mapping, &body);
685 dependences = loop_level_carries_dependences (scop, body, depth);
686 timevar_pop (TV_GRAPHITE_DATA_DEPS);
688 return !dependences;
691 #endif
692 #endif