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>
30 #include <cloog/cloog.h>
31 #include <cloog/isl/domain.h>
35 #include "coretypes.h"
37 #include "basic-block.h"
38 #include "tree-ssa-alias.h"
39 #include "internal-fn.h"
40 #include "gimple-expr.h"
43 #include "gimple-iterator.h"
44 #include "tree-ssa-loop.h"
45 #include "tree-pass.h"
47 #include "tree-chrec.h"
48 #include "tree-data-ref.h"
49 #include "tree-scalar-evolution.h"
53 #include "graphite-poly.h"
54 #include "graphite-htab.h"
57 scop_get_dependences (scop_p scop
)
59 isl_union_map
*dependences
;
62 compute_deps (scop
, SCOP_BBS (scop
),
63 &scop
->must_raw
, &scop
->may_raw
,
64 &scop
->must_raw_no_source
, &scop
->may_raw_no_source
,
65 &scop
->must_war
, &scop
->may_war
,
66 &scop
->must_war_no_source
, &scop
->may_war_no_source
,
67 &scop
->must_waw
, &scop
->may_waw
,
68 &scop
->must_waw_no_source
, &scop
->may_waw_no_source
);
70 dependences
= isl_union_map_copy (scop
->must_raw
);
71 dependences
= isl_union_map_union (dependences
,
72 isl_union_map_copy (scop
->must_war
));
73 dependences
= isl_union_map_union (dependences
,
74 isl_union_map_copy (scop
->must_waw
));
75 dependences
= isl_union_map_union (dependences
,
76 isl_union_map_copy (scop
->may_raw
));
77 dependences
= isl_union_map_union (dependences
,
78 isl_union_map_copy (scop
->may_war
));
79 dependences
= isl_union_map_union (dependences
,
80 isl_union_map_copy (scop
->may_waw
));
85 /* Add the constraints from the set S to the domain of MAP. */
88 constrain_domain (isl_map
*map
, isl_set
*s
)
90 isl_space
*d
= isl_map_get_space (map
);
91 isl_id
*id
= isl_space_get_tuple_id (d
, isl_dim_in
);
93 s
= isl_set_set_tuple_id (s
, id
);
95 return isl_map_intersect_domain (map
, s
);
98 /* Constrain pdr->accesses with pdr->extent and pbb->domain. */
101 add_pdr_constraints (poly_dr_p pdr
, poly_bb_p pbb
)
103 isl_map
*x
= isl_map_intersect_range (isl_map_copy (pdr
->accesses
),
104 isl_set_copy (pdr
->extent
));
105 x
= constrain_domain (x
, isl_set_copy (pbb
->domain
));
109 /* Returns all the memory reads in SCOP. */
111 static isl_union_map
*
112 scop_get_reads (scop_p scop
, vec
<poly_bb_p
> pbbs
)
117 isl_space
*space
= isl_set_get_space (scop
->context
);
118 isl_union_map
*res
= isl_union_map_empty (space
);
120 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
122 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
123 if (pdr_read_p (pdr
))
124 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
130 /* Returns all the memory must writes in SCOP. */
132 static isl_union_map
*
133 scop_get_must_writes (scop_p scop
, vec
<poly_bb_p
> pbbs
)
138 isl_space
*space
= isl_set_get_space (scop
->context
);
139 isl_union_map
*res
= isl_union_map_empty (space
);
141 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
143 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
144 if (pdr_write_p (pdr
))
145 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
151 /* Returns all the memory may writes in SCOP. */
153 static isl_union_map
*
154 scop_get_may_writes (scop_p scop
, vec
<poly_bb_p
> pbbs
)
159 isl_space
*space
= isl_set_get_space (scop
->context
);
160 isl_union_map
*res
= isl_union_map_empty (space
);
162 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
164 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
165 if (pdr_may_write_p (pdr
))
166 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
172 /* Returns all the original schedules in SCOP. */
174 static isl_union_map
*
175 scop_get_original_schedule (scop_p scop
, vec
<poly_bb_p
> pbbs
)
179 isl_space
*space
= isl_set_get_space (scop
->context
);
180 isl_union_map
*res
= isl_union_map_empty (space
);
182 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
184 res
= isl_union_map_add_map
185 (res
, constrain_domain (isl_map_copy (pbb
->schedule
),
186 isl_set_copy (pbb
->domain
)));
192 /* Returns all the transformed schedules in SCOP. */
194 static isl_union_map
*
195 scop_get_transformed_schedule (scop_p scop
, vec
<poly_bb_p
> pbbs
)
199 isl_space
*space
= isl_set_get_space (scop
->context
);
200 isl_union_map
*res
= isl_union_map_empty (space
);
202 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
204 res
= isl_union_map_add_map
205 (res
, constrain_domain (isl_map_copy (pbb
->transformed
),
206 isl_set_copy (pbb
->domain
)));
212 /* Helper function used on each MAP of a isl_union_map. Computes the
213 maximal output dimension. */
216 max_number_of_out_dimensions (__isl_take isl_map
*map
, void *user
)
218 int global_max
= *((int *) user
);
219 isl_space
*space
= isl_map_get_space (map
);
220 int nb_out
= isl_space_dim (space
, isl_dim_out
);
222 if (global_max
< nb_out
)
223 *((int *) user
) = nb_out
;
226 isl_space_free (space
);
230 /* Extends the output dimension of MAP to MAX dimensions. */
232 static __isl_give isl_map
*
233 extend_map (__isl_take isl_map
*map
, int max
)
235 isl_space
*space
= isl_map_get_space (map
);
236 int n
= isl_space_dim (space
, isl_dim_out
);
238 isl_space_free (space
);
239 return isl_map_add_dims (map
, isl_dim_out
, max
- n
);
242 /* Structure used to pass parameters to extend_schedule_1. */
244 struct extend_schedule_str
{
249 /* Helper function for extend_schedule. */
252 extend_schedule_1 (__isl_take isl_map
*map
, void *user
)
254 struct extend_schedule_str
*str
= (struct extend_schedule_str
*) user
;
255 str
->umap
= isl_union_map_add_map (str
->umap
, extend_map (map
, str
->max
));
259 /* Return a relation that has uniform output dimensions. */
261 __isl_give isl_union_map
*
262 extend_schedule (__isl_take isl_union_map
*x
)
266 struct extend_schedule_str str
;
268 res
= isl_union_map_foreach_map (x
, max_number_of_out_dimensions
, (void *) &max
);
269 gcc_assert (res
== 0);
272 str
.umap
= isl_union_map_empty (isl_union_map_get_space (x
));
273 res
= isl_union_map_foreach_map (x
, extend_schedule_1
, (void *) &str
);
274 gcc_assert (res
== 0);
276 isl_union_map_free (x
);
280 /* Applies SCHEDULE to the in and out dimensions of the dependences
281 DEPS and return the resulting relation. */
284 apply_schedule_on_deps (__isl_keep isl_union_map
*schedule
,
285 __isl_keep isl_union_map
*deps
)
288 isl_union_map
*ux
, *trans
;
290 trans
= isl_union_map_copy (schedule
);
291 trans
= extend_schedule (trans
);
292 ux
= isl_union_map_copy (deps
);
293 ux
= isl_union_map_apply_domain (ux
, isl_union_map_copy (trans
));
294 ux
= isl_union_map_apply_range (ux
, trans
);
295 if (isl_union_map_is_empty (ux
))
297 isl_union_map_free (ux
);
300 x
= isl_map_from_union_map (ux
);
305 /* Return true when SCHEDULE does not violate the data DEPS: that is
306 when the intersection of LEX with the DEPS transformed by SCHEDULE
307 is empty. LEX is the relation in which the outputs occur before
311 no_violations (__isl_keep isl_union_map
*schedule
,
312 __isl_keep isl_union_map
*deps
)
318 if (isl_union_map_is_empty (deps
))
321 x
= apply_schedule_on_deps (schedule
, deps
);
322 space
= isl_map_get_space (x
);
323 space
= isl_space_range (space
);
324 lex
= isl_map_lex_ge (space
);
325 x
= isl_map_intersect (x
, lex
);
326 res
= isl_map_is_empty (x
);
332 /* Return true when DEPS is non empty and the intersection of LEX with
333 the DEPS transformed by SCHEDULE is non empty. LEX is the relation
334 in which all the inputs before DEPTH occur at the same time as the
335 output, and the input at DEPTH occurs before output. */
338 carries_deps (__isl_keep isl_union_map
*schedule
,
339 __isl_keep isl_union_map
*deps
,
346 isl_constraint
*ineq
;
348 if (isl_union_map_is_empty (deps
))
351 x
= apply_schedule_on_deps (schedule
, deps
);
354 space
= isl_map_get_space (x
);
355 space
= isl_space_range (space
);
356 lex
= isl_map_lex_le (space
);
357 space
= isl_map_get_space (x
);
358 ineq
= isl_inequality_alloc (isl_local_space_from_space (space
));
360 for (i
= 0; i
< depth
- 1; i
++)
361 lex
= isl_map_equate (lex
, isl_dim_in
, i
, isl_dim_out
, i
);
364 ineq
= isl_constraint_set_coefficient_si (ineq
, isl_dim_out
, depth
- 1, 1);
365 ineq
= isl_constraint_set_coefficient_si (ineq
, isl_dim_in
, depth
- 1, -1);
366 ineq
= isl_constraint_set_constant_si (ineq
, -1);
367 lex
= isl_map_add_constraint (lex
, ineq
);
368 x
= isl_map_intersect (x
, lex
);
369 res
= !isl_map_is_empty (x
);
375 /* Subtract from the RAW, WAR, and WAW dependences those relations
376 that have been marked as belonging to an associative commutative
380 subtract_commutative_associative_deps (scop_p scop
,
382 isl_union_map
*original
,
383 isl_union_map
**must_raw
,
384 isl_union_map
**may_raw
,
385 isl_union_map
**must_raw_no_source
,
386 isl_union_map
**may_raw_no_source
,
387 isl_union_map
**must_war
,
388 isl_union_map
**may_war
,
389 isl_union_map
**must_war_no_source
,
390 isl_union_map
**may_war_no_source
,
391 isl_union_map
**must_waw
,
392 isl_union_map
**may_waw
,
393 isl_union_map
**must_waw_no_source
,
394 isl_union_map
**may_waw_no_source
)
399 isl_space
*space
= isl_set_get_space (scop
->context
);
401 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
402 if (PBB_IS_REDUCTION (pbb
))
405 isl_union_map
*r
= isl_union_map_empty (isl_space_copy (space
));
406 isl_union_map
*must_w
= isl_union_map_empty (isl_space_copy (space
));
407 isl_union_map
*may_w
= isl_union_map_empty (isl_space_copy (space
));
408 isl_union_map
*all_w
;
409 isl_union_map
*empty
;
410 isl_union_map
*x_must_raw
;
411 isl_union_map
*x_may_raw
;
412 isl_union_map
*x_must_raw_no_source
;
413 isl_union_map
*x_may_raw_no_source
;
414 isl_union_map
*x_must_war
;
415 isl_union_map
*x_may_war
;
416 isl_union_map
*x_must_war_no_source
;
417 isl_union_map
*x_may_war_no_source
;
418 isl_union_map
*x_must_waw
;
419 isl_union_map
*x_may_waw
;
420 isl_union_map
*x_must_waw_no_source
;
421 isl_union_map
*x_may_waw_no_source
;
423 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
424 if (pdr_read_p (pdr
))
425 r
= isl_union_map_add_map (r
, add_pdr_constraints (pdr
, pbb
));
427 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
428 if (pdr_write_p (pdr
))
429 must_w
= isl_union_map_add_map (must_w
,
430 add_pdr_constraints (pdr
, pbb
));
432 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
433 if (pdr_may_write_p (pdr
))
434 may_w
= isl_union_map_add_map (may_w
,
435 add_pdr_constraints (pdr
, pbb
));
437 all_w
= isl_union_map_union
438 (isl_union_map_copy (must_w
), isl_union_map_copy (may_w
));
439 empty
= isl_union_map_empty (isl_union_map_get_space (all_w
));
441 res
= isl_union_map_compute_flow (isl_union_map_copy (r
),
442 isl_union_map_copy (must_w
),
443 isl_union_map_copy (may_w
),
444 isl_union_map_copy (original
),
445 &x_must_raw
, &x_may_raw
,
446 &x_must_raw_no_source
,
447 &x_may_raw_no_source
);
448 gcc_assert (res
== 0);
449 res
= isl_union_map_compute_flow (isl_union_map_copy (all_w
),
451 isl_union_map_copy (original
),
452 &x_must_war
, &x_may_war
,
453 &x_must_war_no_source
,
454 &x_may_war_no_source
);
455 gcc_assert (res
== 0);
456 res
= isl_union_map_compute_flow (all_w
, must_w
, may_w
,
457 isl_union_map_copy (original
),
458 &x_must_waw
, &x_may_waw
,
459 &x_must_waw_no_source
,
460 &x_may_waw_no_source
);
461 gcc_assert (res
== 0);
464 *must_raw
= isl_union_map_subtract (*must_raw
, x_must_raw
);
466 isl_union_map_free (x_must_raw
);
469 *may_raw
= isl_union_map_subtract (*may_raw
, x_may_raw
);
471 isl_union_map_free (x_may_raw
);
473 if (must_raw_no_source
)
474 *must_raw_no_source
= isl_union_map_subtract (*must_raw_no_source
,
475 x_must_raw_no_source
);
477 isl_union_map_free (x_must_raw_no_source
);
479 if (may_raw_no_source
)
480 *may_raw_no_source
= isl_union_map_subtract (*may_raw_no_source
,
481 x_may_raw_no_source
);
483 isl_union_map_free (x_may_raw_no_source
);
486 *must_war
= isl_union_map_subtract (*must_war
, x_must_war
);
488 isl_union_map_free (x_must_war
);
491 *may_war
= isl_union_map_subtract (*may_war
, x_may_war
);
493 isl_union_map_free (x_may_war
);
495 if (must_war_no_source
)
496 *must_war_no_source
= isl_union_map_subtract (*must_war_no_source
,
497 x_must_war_no_source
);
499 isl_union_map_free (x_must_war_no_source
);
501 if (may_war_no_source
)
502 *may_war_no_source
= isl_union_map_subtract (*may_war_no_source
,
503 x_may_war_no_source
);
505 isl_union_map_free (x_may_war_no_source
);
508 *must_waw
= isl_union_map_subtract (*must_waw
, x_must_waw
);
510 isl_union_map_free (x_must_waw
);
513 *may_waw
= isl_union_map_subtract (*may_waw
, x_may_waw
);
515 isl_union_map_free (x_may_waw
);
517 if (must_waw_no_source
)
518 *must_waw_no_source
= isl_union_map_subtract (*must_waw_no_source
,
519 x_must_waw_no_source
);
521 isl_union_map_free (x_must_waw_no_source
);
523 if (may_waw_no_source
)
524 *may_waw_no_source
= isl_union_map_subtract (*may_waw_no_source
,
525 x_may_waw_no_source
);
527 isl_union_map_free (x_may_waw_no_source
);
530 isl_union_map_free (original
);
531 isl_space_free (space
);
534 /* Compute the original data dependences in SCOP for all the reads and
538 compute_deps (scop_p scop
, vec
<poly_bb_p
> pbbs
,
539 isl_union_map
**must_raw
,
540 isl_union_map
**may_raw
,
541 isl_union_map
**must_raw_no_source
,
542 isl_union_map
**may_raw_no_source
,
543 isl_union_map
**must_war
,
544 isl_union_map
**may_war
,
545 isl_union_map
**must_war_no_source
,
546 isl_union_map
**may_war_no_source
,
547 isl_union_map
**must_waw
,
548 isl_union_map
**may_waw
,
549 isl_union_map
**must_waw_no_source
,
550 isl_union_map
**may_waw_no_source
)
552 isl_union_map
*reads
= scop_get_reads (scop
, pbbs
);
553 isl_union_map
*must_writes
= scop_get_must_writes (scop
, pbbs
);
554 isl_union_map
*may_writes
= scop_get_may_writes (scop
, pbbs
);
555 isl_union_map
*all_writes
= isl_union_map_union
556 (isl_union_map_copy (must_writes
), isl_union_map_copy (may_writes
));
557 isl_space
*space
= isl_union_map_get_space (all_writes
);
558 isl_union_map
*empty
= isl_union_map_empty (space
);
559 isl_union_map
*original
= scop_get_original_schedule (scop
, pbbs
);
562 res
= isl_union_map_compute_flow (isl_union_map_copy (reads
),
563 isl_union_map_copy (must_writes
),
564 isl_union_map_copy (may_writes
),
565 isl_union_map_copy (original
),
566 must_raw
, may_raw
, must_raw_no_source
,
568 gcc_assert (res
== 0);
569 res
= isl_union_map_compute_flow (isl_union_map_copy (all_writes
),
571 isl_union_map_copy (original
),
572 must_war
, may_war
, must_war_no_source
,
574 gcc_assert (res
== 0);
575 res
= isl_union_map_compute_flow (all_writes
, must_writes
, may_writes
,
576 isl_union_map_copy (original
),
577 must_waw
, may_waw
, must_waw_no_source
,
579 gcc_assert (res
== 0);
581 subtract_commutative_associative_deps
582 (scop
, pbbs
, original
,
583 must_raw
, may_raw
, must_raw_no_source
, may_raw_no_source
,
584 must_war
, may_war
, must_war_no_source
, may_war_no_source
,
585 must_waw
, may_waw
, must_waw_no_source
, may_waw_no_source
);
588 /* Given a TRANSFORM, check whether it respects the original
589 dependences in SCOP. Returns true when TRANSFORM is a safe
593 transform_is_safe (scop_p scop
, isl_union_map
*transform
)
598 compute_deps (scop
, SCOP_BBS (scop
),
599 &scop
->must_raw
, &scop
->may_raw
,
600 &scop
->must_raw_no_source
, &scop
->may_raw_no_source
,
601 &scop
->must_war
, &scop
->may_war
,
602 &scop
->must_war_no_source
, &scop
->may_war_no_source
,
603 &scop
->must_waw
, &scop
->may_waw
,
604 &scop
->must_waw_no_source
, &scop
->may_waw_no_source
);
606 res
= (no_violations (transform
, scop
->must_raw
)
607 && no_violations (transform
, scop
->may_raw
)
608 && no_violations (transform
, scop
->must_war
)
609 && no_violations (transform
, scop
->may_war
)
610 && no_violations (transform
, scop
->must_waw
)
611 && no_violations (transform
, scop
->may_waw
));
613 isl_union_map_free (transform
);
617 /* Return true when the SCOP transformed schedule is correct. */
620 graphite_legal_transform (scop_p scop
)
623 isl_union_map
*transform
;
625 timevar_push (TV_GRAPHITE_DATA_DEPS
);
626 transform
= scop_get_transformed_schedule (scop
, SCOP_BBS (scop
));
627 res
= transform_is_safe (scop
, transform
);
628 timevar_pop (TV_GRAPHITE_DATA_DEPS
);
633 /* Return true when the loop at DEPTH carries dependences. BODY is
634 the body of the loop. */
637 loop_level_carries_dependences (scop_p scop
, vec
<poly_bb_p
> body
,
640 isl_union_map
*transform
= scop_get_transformed_schedule (scop
, body
);
641 isl_union_map
*must_raw
, *may_raw
;
642 isl_union_map
*must_war
, *may_war
;
643 isl_union_map
*must_waw
, *may_waw
;
646 compute_deps (scop
, body
,
647 &must_raw
, &may_raw
, NULL
, NULL
,
648 &must_war
, &may_war
, NULL
, NULL
,
649 &must_waw
, &may_waw
, NULL
, NULL
);
651 res
= (carries_deps (transform
, must_raw
, depth
)
652 || carries_deps (transform
, may_raw
, depth
)
653 || carries_deps (transform
, must_war
, depth
)
654 || carries_deps (transform
, may_war
, depth
)
655 || carries_deps (transform
, must_waw
, depth
)
656 || carries_deps (transform
, may_waw
, depth
));
658 isl_union_map_free (transform
);
659 isl_union_map_free (must_raw
);
660 isl_union_map_free (may_raw
);
661 isl_union_map_free (must_war
);
662 isl_union_map_free (may_war
);
663 isl_union_map_free (must_waw
);
664 isl_union_map_free (may_waw
);
668 /* Returns true when the loop L at level DEPTH is parallel.
669 BB_PBB_MAPPING is a map between a basic_block and its related
673 loop_is_parallel_p (loop_p loop
, bb_pbb_htab_type
*bb_pbb_mapping
, int depth
)
678 timevar_push (TV_GRAPHITE_DATA_DEPS
);
679 auto_vec
<poly_bb_p
, 3> body
;
680 scop
= get_loop_body_pbbs (loop
, bb_pbb_mapping
, &body
);
681 dependences
= loop_level_carries_dependences (scop
, body
, depth
);
682 timevar_pop (TV_GRAPHITE_DATA_DEPS
);