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)
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>
31 #include <cloog/cloog.h>
32 #include <cloog/isl/domain.h>
37 #include "coretypes.h"
39 #include "basic-block.h"
40 #include "tree-ssa-alias.h"
41 #include "internal-fn.h"
42 #include "gimple-expr.h"
45 #include "gimple-iterator.h"
46 #include "tree-ssa-loop.h"
47 #include "tree-pass.h"
49 #include "tree-chrec.h"
50 #include "tree-data-ref.h"
51 #include "tree-scalar-evolution.h"
55 #include "graphite-poly.h"
56 #include "graphite-htab.h"
59 scop_get_dependences (scop_p scop
)
61 isl_union_map
*dependences
;
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
));
87 /* Add the constraints from the set S to the domain of 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
);
97 return isl_map_intersect_domain (map
, s
);
100 /* Constrain pdr->accesses with pdr->extent and pbb->domain. */
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
));
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
)
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
));
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
)
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
));
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
)
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
));
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
)
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
)));
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
)
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
)));
214 /* Helper function used on each MAP of a isl_union_map. Computes the
215 maximal output dimension. */
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
;
228 isl_space_free (space
);
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
{
251 /* Helper function for extend_schedule. */
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
));
261 /* Return a relation that has uniform output dimensions. */
263 __isl_give isl_union_map
*
264 extend_schedule (__isl_take isl_union_map
*x
)
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);
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
);
282 /* Applies SCHEDULE to the in and out dimensions of the dependences
283 DEPS and return the resulting relation. */
286 apply_schedule_on_deps (__isl_keep isl_union_map
*schedule
,
287 __isl_keep isl_union_map
*deps
)
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
);
302 x
= isl_map_from_union_map (ux
);
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
313 no_violations (__isl_keep isl_union_map
*schedule
,
314 __isl_keep isl_union_map
*deps
)
320 if (isl_union_map_is_empty (deps
))
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
);
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. */
340 carries_deps (__isl_keep isl_union_map
*schedule
,
341 __isl_keep isl_union_map
*deps
,
348 isl_constraint
*ineq
;
350 if (isl_union_map_is_empty (deps
))
353 x
= apply_schedule_on_deps (schedule
, deps
);
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
);
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
);
377 /* Subtract from the RAW, WAR, and WAW dependences those relations
378 that have been marked as belonging to an associative commutative
382 subtract_commutative_associative_deps (scop_p scop
,
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
)
401 isl_space
*space
= isl_set_get_space (scop
->context
);
403 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
404 if (PBB_IS_REDUCTION (pbb
))
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
),
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);
466 *must_raw
= isl_union_map_subtract (*must_raw
, x_must_raw
);
468 isl_union_map_free (x_must_raw
);
471 *may_raw
= isl_union_map_subtract (*may_raw
, x_may_raw
);
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
);
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
);
485 isl_union_map_free (x_may_raw_no_source
);
488 *must_war
= isl_union_map_subtract (*must_war
, x_must_war
);
490 isl_union_map_free (x_must_war
);
493 *may_war
= isl_union_map_subtract (*may_war
, x_may_war
);
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
);
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
);
507 isl_union_map_free (x_may_war_no_source
);
510 *must_waw
= isl_union_map_subtract (*must_waw
, x_must_waw
);
512 isl_union_map_free (x_must_waw
);
515 *may_waw
= isl_union_map_subtract (*may_waw
, x_may_waw
);
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
);
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
);
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
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
);
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
,
570 gcc_assert (res
== 0);
571 res
= isl_union_map_compute_flow (isl_union_map_copy (all_writes
),
573 isl_union_map_copy (original
),
574 must_war
, may_war
, must_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
,
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
595 transform_is_safe (scop_p scop
, isl_union_map
*transform
)
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
);
619 /* Return true when the SCOP transformed schedule is correct. */
622 graphite_legal_transform (scop_p scop
)
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
);
637 /* Return true when the loop at DEPTH carries dependences. BODY is
638 the body of the loop. */
641 loop_level_carries_dependences (scop_p scop
, vec
<poly_bb_p
> body
,
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
;
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
);
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
677 loop_is_parallel_p (loop_p loop
, bb_pbb_htab_type
*bb_pbb_mapping
, int depth
)
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
);