1 /* Data dependence analysis for Graphite.
2 Copyright (C) 2009-2015 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)
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/>. */
27 #include <isl/union_map.h>
29 #include <isl/constraint.h>
33 #include "coretypes.h"
42 #include "fold-const.h"
45 #include "hard-reg-set.h"
48 #include "dominance.h"
50 #include "basic-block.h"
51 #include "tree-ssa-alias.h"
52 #include "internal-fn.h"
53 #include "gimple-expr.h"
56 #include "gimple-iterator.h"
57 #include "tree-ssa-loop.h"
58 #include "tree-pass.h"
60 #include "tree-chrec.h"
61 #include "tree-data-ref.h"
62 #include "tree-scalar-evolution.h"
66 #include "graphite-poly.h"
69 scop_get_dependences (scop_p scop
)
71 isl_union_map
*dependences
;
74 compute_deps (scop
, SCOP_BBS (scop
),
75 &scop
->must_raw
, &scop
->may_raw
,
76 &scop
->must_raw_no_source
, &scop
->may_raw_no_source
,
77 &scop
->must_war
, &scop
->may_war
,
78 &scop
->must_war_no_source
, &scop
->may_war_no_source
,
79 &scop
->must_waw
, &scop
->may_waw
,
80 &scop
->must_waw_no_source
, &scop
->may_waw_no_source
);
82 dependences
= isl_union_map_copy (scop
->must_raw
);
83 dependences
= isl_union_map_union (dependences
,
84 isl_union_map_copy (scop
->must_war
));
85 dependences
= isl_union_map_union (dependences
,
86 isl_union_map_copy (scop
->must_waw
));
87 dependences
= isl_union_map_union (dependences
,
88 isl_union_map_copy (scop
->may_raw
));
89 dependences
= isl_union_map_union (dependences
,
90 isl_union_map_copy (scop
->may_war
));
91 dependences
= isl_union_map_union (dependences
,
92 isl_union_map_copy (scop
->may_waw
));
97 /* Add the constraints from the set S to the domain of MAP. */
100 constrain_domain (isl_map
*map
, isl_set
*s
)
102 isl_space
*d
= isl_map_get_space (map
);
103 isl_id
*id
= isl_space_get_tuple_id (d
, isl_dim_in
);
105 s
= isl_set_set_tuple_id (s
, id
);
107 return isl_map_intersect_domain (map
, s
);
110 /* Constrain pdr->accesses with pdr->extent and pbb->domain. */
113 add_pdr_constraints (poly_dr_p pdr
, poly_bb_p pbb
)
115 isl_map
*x
= isl_map_intersect_range (isl_map_copy (pdr
->accesses
),
116 isl_set_copy (pdr
->extent
));
117 x
= constrain_domain (x
, isl_set_copy (pbb
->domain
));
121 /* Returns all the memory reads in SCOP. */
123 static isl_union_map
*
124 scop_get_reads (scop_p scop
, vec
<poly_bb_p
> pbbs
)
129 isl_space
*space
= isl_set_get_space (scop
->context
);
130 isl_union_map
*res
= isl_union_map_empty (space
);
132 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
134 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
135 if (pdr_read_p (pdr
))
136 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
142 /* Returns all the memory must writes in SCOP. */
144 static isl_union_map
*
145 scop_get_must_writes (scop_p scop
, vec
<poly_bb_p
> pbbs
)
150 isl_space
*space
= isl_set_get_space (scop
->context
);
151 isl_union_map
*res
= isl_union_map_empty (space
);
153 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
155 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
156 if (pdr_write_p (pdr
))
157 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
163 /* Returns all the memory may writes in SCOP. */
165 static isl_union_map
*
166 scop_get_may_writes (scop_p scop
, vec
<poly_bb_p
> pbbs
)
171 isl_space
*space
= isl_set_get_space (scop
->context
);
172 isl_union_map
*res
= isl_union_map_empty (space
);
174 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
176 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
177 if (pdr_may_write_p (pdr
))
178 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
184 /* Returns all the original schedules in SCOP. */
186 static isl_union_map
*
187 scop_get_original_schedule (scop_p scop
, vec
<poly_bb_p
> pbbs
)
191 isl_space
*space
= isl_set_get_space (scop
->context
);
192 isl_union_map
*res
= isl_union_map_empty (space
);
194 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
196 res
= isl_union_map_add_map
197 (res
, constrain_domain (isl_map_copy (pbb
->schedule
),
198 isl_set_copy (pbb
->domain
)));
204 /* Returns all the transformed schedules in SCOP. */
206 static isl_union_map
*
207 scop_get_transformed_schedule (scop_p scop
, vec
<poly_bb_p
> pbbs
)
211 isl_space
*space
= isl_set_get_space (scop
->context
);
212 isl_union_map
*res
= isl_union_map_empty (space
);
214 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
216 res
= isl_union_map_add_map
217 (res
, constrain_domain (isl_map_copy (pbb
->transformed
),
218 isl_set_copy (pbb
->domain
)));
224 /* Helper function used on each MAP of a isl_union_map. Computes the
225 maximal output dimension. */
228 max_number_of_out_dimensions (__isl_take isl_map
*map
, void *user
)
230 int global_max
= *((int *) user
);
231 isl_space
*space
= isl_map_get_space (map
);
232 int nb_out
= isl_space_dim (space
, isl_dim_out
);
234 if (global_max
< nb_out
)
235 *((int *) user
) = nb_out
;
238 isl_space_free (space
);
242 /* Extends the output dimension of MAP to MAX dimensions. */
244 static __isl_give isl_map
*
245 extend_map (__isl_take isl_map
*map
, int max
)
247 isl_space
*space
= isl_map_get_space (map
);
248 int n
= isl_space_dim (space
, isl_dim_out
);
250 isl_space_free (space
);
251 return isl_map_add_dims (map
, isl_dim_out
, max
- n
);
254 /* Structure used to pass parameters to extend_schedule_1. */
256 struct extend_schedule_str
{
261 /* Helper function for extend_schedule. */
264 extend_schedule_1 (__isl_take isl_map
*map
, void *user
)
266 struct extend_schedule_str
*str
= (struct extend_schedule_str
*) user
;
267 str
->umap
= isl_union_map_add_map (str
->umap
, extend_map (map
, str
->max
));
271 /* Return a relation that has uniform output dimensions. */
273 __isl_give isl_union_map
*
274 extend_schedule (__isl_take isl_union_map
*x
)
278 struct extend_schedule_str str
;
280 res
= isl_union_map_foreach_map (x
, max_number_of_out_dimensions
, (void *) &max
);
281 gcc_assert (res
== 0);
284 str
.umap
= isl_union_map_empty (isl_union_map_get_space (x
));
285 res
= isl_union_map_foreach_map (x
, extend_schedule_1
, (void *) &str
);
286 gcc_assert (res
== 0);
288 isl_union_map_free (x
);
292 /* Applies SCHEDULE to the in and out dimensions of the dependences
293 DEPS and return the resulting relation. */
296 apply_schedule_on_deps (__isl_keep isl_union_map
*schedule
,
297 __isl_keep isl_union_map
*deps
)
300 isl_union_map
*ux
, *trans
;
302 trans
= isl_union_map_copy (schedule
);
303 trans
= extend_schedule (trans
);
304 ux
= isl_union_map_copy (deps
);
305 ux
= isl_union_map_apply_domain (ux
, isl_union_map_copy (trans
));
306 ux
= isl_union_map_apply_range (ux
, trans
);
307 if (isl_union_map_is_empty (ux
))
309 isl_union_map_free (ux
);
312 x
= isl_map_from_union_map (ux
);
317 /* Return true when SCHEDULE does not violate the data DEPS: that is
318 when the intersection of LEX with the DEPS transformed by SCHEDULE
319 is empty. LEX is the relation in which the outputs occur before
323 no_violations (__isl_keep isl_union_map
*schedule
,
324 __isl_keep isl_union_map
*deps
)
330 if (isl_union_map_is_empty (deps
))
333 x
= apply_schedule_on_deps (schedule
, deps
);
334 space
= isl_map_get_space (x
);
335 space
= isl_space_range (space
);
336 lex
= isl_map_lex_ge (space
);
337 x
= isl_map_intersect (x
, lex
);
338 res
= isl_map_is_empty (x
);
344 /* Return true when DEPS is non empty and the intersection of LEX with
345 the DEPS transformed by SCHEDULE is non empty. LEX is the relation
346 in which all the inputs before DEPTH occur at the same time as the
347 output, and the input at DEPTH occurs before output. */
350 carries_deps (__isl_keep isl_union_map
*schedule
,
351 __isl_keep isl_union_map
*deps
,
358 isl_constraint
*ineq
;
360 if (isl_union_map_is_empty (deps
))
363 x
= apply_schedule_on_deps (schedule
, deps
);
366 space
= isl_map_get_space (x
);
367 space
= isl_space_range (space
);
368 lex
= isl_map_lex_le (space
);
369 space
= isl_map_get_space (x
);
370 ineq
= isl_inequality_alloc (isl_local_space_from_space (space
));
372 for (i
= 0; i
< depth
- 1; i
++)
373 lex
= isl_map_equate (lex
, isl_dim_in
, i
, isl_dim_out
, i
);
376 ineq
= isl_constraint_set_coefficient_si (ineq
, isl_dim_out
, depth
- 1, 1);
377 ineq
= isl_constraint_set_coefficient_si (ineq
, isl_dim_in
, depth
- 1, -1);
378 ineq
= isl_constraint_set_constant_si (ineq
, -1);
379 lex
= isl_map_add_constraint (lex
, ineq
);
380 x
= isl_map_intersect (x
, lex
);
381 res
= !isl_map_is_empty (x
);
387 /* Subtract from the RAW, WAR, and WAW dependences those relations
388 that have been marked as belonging to an associative commutative
392 subtract_commutative_associative_deps (scop_p scop
,
394 isl_union_map
*original
,
395 isl_union_map
**must_raw
,
396 isl_union_map
**may_raw
,
397 isl_union_map
**must_raw_no_source
,
398 isl_union_map
**may_raw_no_source
,
399 isl_union_map
**must_war
,
400 isl_union_map
**may_war
,
401 isl_union_map
**must_war_no_source
,
402 isl_union_map
**may_war_no_source
,
403 isl_union_map
**must_waw
,
404 isl_union_map
**may_waw
,
405 isl_union_map
**must_waw_no_source
,
406 isl_union_map
**may_waw_no_source
)
411 isl_space
*space
= isl_set_get_space (scop
->context
);
413 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
414 if (PBB_IS_REDUCTION (pbb
))
417 isl_union_map
*r
= isl_union_map_empty (isl_space_copy (space
));
418 isl_union_map
*must_w
= isl_union_map_empty (isl_space_copy (space
));
419 isl_union_map
*may_w
= isl_union_map_empty (isl_space_copy (space
));
420 isl_union_map
*all_w
;
421 isl_union_map
*empty
;
422 isl_union_map
*x_must_raw
;
423 isl_union_map
*x_may_raw
;
424 isl_union_map
*x_must_raw_no_source
;
425 isl_union_map
*x_may_raw_no_source
;
426 isl_union_map
*x_must_war
;
427 isl_union_map
*x_may_war
;
428 isl_union_map
*x_must_war_no_source
;
429 isl_union_map
*x_may_war_no_source
;
430 isl_union_map
*x_must_waw
;
431 isl_union_map
*x_may_waw
;
432 isl_union_map
*x_must_waw_no_source
;
433 isl_union_map
*x_may_waw_no_source
;
435 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
436 if (pdr_read_p (pdr
))
437 r
= isl_union_map_add_map (r
, add_pdr_constraints (pdr
, pbb
));
439 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
440 if (pdr_write_p (pdr
))
441 must_w
= isl_union_map_add_map (must_w
,
442 add_pdr_constraints (pdr
, pbb
));
444 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
445 if (pdr_may_write_p (pdr
))
446 may_w
= isl_union_map_add_map (may_w
,
447 add_pdr_constraints (pdr
, pbb
));
449 all_w
= isl_union_map_union
450 (isl_union_map_copy (must_w
), isl_union_map_copy (may_w
));
451 empty
= isl_union_map_empty (isl_union_map_get_space (all_w
));
453 res
= isl_union_map_compute_flow (isl_union_map_copy (r
),
454 isl_union_map_copy (must_w
),
455 isl_union_map_copy (may_w
),
456 isl_union_map_copy (original
),
457 &x_must_raw
, &x_may_raw
,
458 &x_must_raw_no_source
,
459 &x_may_raw_no_source
);
460 gcc_assert (res
== 0);
461 res
= isl_union_map_compute_flow (isl_union_map_copy (all_w
),
463 isl_union_map_copy (original
),
464 &x_must_war
, &x_may_war
,
465 &x_must_war_no_source
,
466 &x_may_war_no_source
);
467 gcc_assert (res
== 0);
468 res
= isl_union_map_compute_flow (all_w
, must_w
, may_w
,
469 isl_union_map_copy (original
),
470 &x_must_waw
, &x_may_waw
,
471 &x_must_waw_no_source
,
472 &x_may_waw_no_source
);
473 gcc_assert (res
== 0);
476 *must_raw
= isl_union_map_subtract (*must_raw
, x_must_raw
);
478 isl_union_map_free (x_must_raw
);
481 *may_raw
= isl_union_map_subtract (*may_raw
, x_may_raw
);
483 isl_union_map_free (x_may_raw
);
485 if (must_raw_no_source
)
486 *must_raw_no_source
= isl_union_map_subtract (*must_raw_no_source
,
487 x_must_raw_no_source
);
489 isl_union_map_free (x_must_raw_no_source
);
491 if (may_raw_no_source
)
492 *may_raw_no_source
= isl_union_map_subtract (*may_raw_no_source
,
493 x_may_raw_no_source
);
495 isl_union_map_free (x_may_raw_no_source
);
498 *must_war
= isl_union_map_subtract (*must_war
, x_must_war
);
500 isl_union_map_free (x_must_war
);
503 *may_war
= isl_union_map_subtract (*may_war
, x_may_war
);
505 isl_union_map_free (x_may_war
);
507 if (must_war_no_source
)
508 *must_war_no_source
= isl_union_map_subtract (*must_war_no_source
,
509 x_must_war_no_source
);
511 isl_union_map_free (x_must_war_no_source
);
513 if (may_war_no_source
)
514 *may_war_no_source
= isl_union_map_subtract (*may_war_no_source
,
515 x_may_war_no_source
);
517 isl_union_map_free (x_may_war_no_source
);
520 *must_waw
= isl_union_map_subtract (*must_waw
, x_must_waw
);
522 isl_union_map_free (x_must_waw
);
525 *may_waw
= isl_union_map_subtract (*may_waw
, x_may_waw
);
527 isl_union_map_free (x_may_waw
);
529 if (must_waw_no_source
)
530 *must_waw_no_source
= isl_union_map_subtract (*must_waw_no_source
,
531 x_must_waw_no_source
);
533 isl_union_map_free (x_must_waw_no_source
);
535 if (may_waw_no_source
)
536 *may_waw_no_source
= isl_union_map_subtract (*may_waw_no_source
,
537 x_may_waw_no_source
);
539 isl_union_map_free (x_may_waw_no_source
);
542 isl_union_map_free (original
);
543 isl_space_free (space
);
546 /* Compute the original data dependences in SCOP for all the reads and
550 compute_deps (scop_p scop
, vec
<poly_bb_p
> pbbs
,
551 isl_union_map
**must_raw
,
552 isl_union_map
**may_raw
,
553 isl_union_map
**must_raw_no_source
,
554 isl_union_map
**may_raw_no_source
,
555 isl_union_map
**must_war
,
556 isl_union_map
**may_war
,
557 isl_union_map
**must_war_no_source
,
558 isl_union_map
**may_war_no_source
,
559 isl_union_map
**must_waw
,
560 isl_union_map
**may_waw
,
561 isl_union_map
**must_waw_no_source
,
562 isl_union_map
**may_waw_no_source
)
564 isl_union_map
*reads
= scop_get_reads (scop
, pbbs
);
565 isl_union_map
*must_writes
= scop_get_must_writes (scop
, pbbs
);
566 isl_union_map
*may_writes
= scop_get_may_writes (scop
, pbbs
);
567 isl_union_map
*all_writes
= isl_union_map_union
568 (isl_union_map_copy (must_writes
), isl_union_map_copy (may_writes
));
569 isl_space
*space
= isl_union_map_get_space (all_writes
);
570 isl_union_map
*empty
= isl_union_map_empty (space
);
571 isl_union_map
*original
= scop_get_original_schedule (scop
, pbbs
);
574 res
= isl_union_map_compute_flow (isl_union_map_copy (reads
),
575 isl_union_map_copy (must_writes
),
576 isl_union_map_copy (may_writes
),
577 isl_union_map_copy (original
),
578 must_raw
, may_raw
, must_raw_no_source
,
580 gcc_assert (res
== 0);
581 res
= isl_union_map_compute_flow (isl_union_map_copy (all_writes
),
583 isl_union_map_copy (original
),
584 must_war
, may_war
, must_war_no_source
,
586 gcc_assert (res
== 0);
587 res
= isl_union_map_compute_flow (all_writes
, must_writes
, may_writes
,
588 isl_union_map_copy (original
),
589 must_waw
, may_waw
, must_waw_no_source
,
591 gcc_assert (res
== 0);
593 subtract_commutative_associative_deps
594 (scop
, pbbs
, original
,
595 must_raw
, may_raw
, must_raw_no_source
, may_raw_no_source
,
596 must_war
, may_war
, must_war_no_source
, may_war_no_source
,
597 must_waw
, may_waw
, must_waw_no_source
, may_waw_no_source
);
600 /* Given a TRANSFORM, check whether it respects the original
601 dependences in SCOP. Returns true when TRANSFORM is a safe
605 transform_is_safe (scop_p scop
, isl_union_map
*transform
)
610 compute_deps (scop
, SCOP_BBS (scop
),
611 &scop
->must_raw
, &scop
->may_raw
,
612 &scop
->must_raw_no_source
, &scop
->may_raw_no_source
,
613 &scop
->must_war
, &scop
->may_war
,
614 &scop
->must_war_no_source
, &scop
->may_war_no_source
,
615 &scop
->must_waw
, &scop
->may_waw
,
616 &scop
->must_waw_no_source
, &scop
->may_waw_no_source
);
618 res
= (no_violations (transform
, scop
->must_raw
)
619 && no_violations (transform
, scop
->may_raw
)
620 && no_violations (transform
, scop
->must_war
)
621 && no_violations (transform
, scop
->may_war
)
622 && no_violations (transform
, scop
->must_waw
)
623 && no_violations (transform
, scop
->may_waw
));
625 isl_union_map_free (transform
);
629 /* Return true when the SCOP transformed schedule is correct. */
632 graphite_legal_transform (scop_p scop
)
635 isl_union_map
*transform
;
637 timevar_push (TV_GRAPHITE_DATA_DEPS
);
638 transform
= scop_get_transformed_schedule (scop
, SCOP_BBS (scop
));
639 res
= transform_is_safe (scop
, transform
);
640 timevar_pop (TV_GRAPHITE_DATA_DEPS
);