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"
37 #include "double-int.h"
45 #include "fold-const.h"
48 #include "hard-reg-set.h"
51 #include "dominance.h"
53 #include "basic-block.h"
54 #include "tree-ssa-alias.h"
55 #include "internal-fn.h"
56 #include "gimple-expr.h"
59 #include "gimple-iterator.h"
60 #include "tree-ssa-loop.h"
61 #include "tree-pass.h"
63 #include "tree-chrec.h"
64 #include "tree-data-ref.h"
65 #include "tree-scalar-evolution.h"
69 #include "graphite-poly.h"
72 scop_get_dependences (scop_p scop
)
74 isl_union_map
*dependences
;
77 compute_deps (scop
, SCOP_BBS (scop
),
78 &scop
->must_raw
, &scop
->may_raw
,
79 &scop
->must_raw_no_source
, &scop
->may_raw_no_source
,
80 &scop
->must_war
, &scop
->may_war
,
81 &scop
->must_war_no_source
, &scop
->may_war_no_source
,
82 &scop
->must_waw
, &scop
->may_waw
,
83 &scop
->must_waw_no_source
, &scop
->may_waw_no_source
);
85 dependences
= isl_union_map_copy (scop
->must_raw
);
86 dependences
= isl_union_map_union (dependences
,
87 isl_union_map_copy (scop
->must_war
));
88 dependences
= isl_union_map_union (dependences
,
89 isl_union_map_copy (scop
->must_waw
));
90 dependences
= isl_union_map_union (dependences
,
91 isl_union_map_copy (scop
->may_raw
));
92 dependences
= isl_union_map_union (dependences
,
93 isl_union_map_copy (scop
->may_war
));
94 dependences
= isl_union_map_union (dependences
,
95 isl_union_map_copy (scop
->may_waw
));
100 /* Add the constraints from the set S to the domain of MAP. */
103 constrain_domain (isl_map
*map
, isl_set
*s
)
105 isl_space
*d
= isl_map_get_space (map
);
106 isl_id
*id
= isl_space_get_tuple_id (d
, isl_dim_in
);
108 s
= isl_set_set_tuple_id (s
, id
);
110 return isl_map_intersect_domain (map
, s
);
113 /* Constrain pdr->accesses with pdr->extent and pbb->domain. */
116 add_pdr_constraints (poly_dr_p pdr
, poly_bb_p pbb
)
118 isl_map
*x
= isl_map_intersect_range (isl_map_copy (pdr
->accesses
),
119 isl_set_copy (pdr
->extent
));
120 x
= constrain_domain (x
, isl_set_copy (pbb
->domain
));
124 /* Returns all the memory reads in SCOP. */
126 static isl_union_map
*
127 scop_get_reads (scop_p scop
, vec
<poly_bb_p
> pbbs
)
132 isl_space
*space
= isl_set_get_space (scop
->context
);
133 isl_union_map
*res
= isl_union_map_empty (space
);
135 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
137 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
138 if (pdr_read_p (pdr
))
139 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
145 /* Returns all the memory must writes in SCOP. */
147 static isl_union_map
*
148 scop_get_must_writes (scop_p scop
, vec
<poly_bb_p
> pbbs
)
153 isl_space
*space
= isl_set_get_space (scop
->context
);
154 isl_union_map
*res
= isl_union_map_empty (space
);
156 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
158 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
159 if (pdr_write_p (pdr
))
160 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
166 /* Returns all the memory may writes in SCOP. */
168 static isl_union_map
*
169 scop_get_may_writes (scop_p scop
, vec
<poly_bb_p
> pbbs
)
174 isl_space
*space
= isl_set_get_space (scop
->context
);
175 isl_union_map
*res
= isl_union_map_empty (space
);
177 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
179 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
180 if (pdr_may_write_p (pdr
))
181 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
187 /* Returns all the original schedules in SCOP. */
189 static isl_union_map
*
190 scop_get_original_schedule (scop_p scop
, vec
<poly_bb_p
> pbbs
)
194 isl_space
*space
= isl_set_get_space (scop
->context
);
195 isl_union_map
*res
= isl_union_map_empty (space
);
197 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
199 res
= isl_union_map_add_map
200 (res
, constrain_domain (isl_map_copy (pbb
->schedule
),
201 isl_set_copy (pbb
->domain
)));
207 /* Returns all the transformed schedules in SCOP. */
209 static isl_union_map
*
210 scop_get_transformed_schedule (scop_p scop
, vec
<poly_bb_p
> pbbs
)
214 isl_space
*space
= isl_set_get_space (scop
->context
);
215 isl_union_map
*res
= isl_union_map_empty (space
);
217 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
219 res
= isl_union_map_add_map
220 (res
, constrain_domain (isl_map_copy (pbb
->transformed
),
221 isl_set_copy (pbb
->domain
)));
227 /* Helper function used on each MAP of a isl_union_map. Computes the
228 maximal output dimension. */
231 max_number_of_out_dimensions (__isl_take isl_map
*map
, void *user
)
233 int global_max
= *((int *) user
);
234 isl_space
*space
= isl_map_get_space (map
);
235 int nb_out
= isl_space_dim (space
, isl_dim_out
);
237 if (global_max
< nb_out
)
238 *((int *) user
) = nb_out
;
241 isl_space_free (space
);
245 /* Extends the output dimension of MAP to MAX dimensions. */
247 static __isl_give isl_map
*
248 extend_map (__isl_take isl_map
*map
, int max
)
250 isl_space
*space
= isl_map_get_space (map
);
251 int n
= isl_space_dim (space
, isl_dim_out
);
253 isl_space_free (space
);
254 return isl_map_add_dims (map
, isl_dim_out
, max
- n
);
257 /* Structure used to pass parameters to extend_schedule_1. */
259 struct extend_schedule_str
{
264 /* Helper function for extend_schedule. */
267 extend_schedule_1 (__isl_take isl_map
*map
, void *user
)
269 struct extend_schedule_str
*str
= (struct extend_schedule_str
*) user
;
270 str
->umap
= isl_union_map_add_map (str
->umap
, extend_map (map
, str
->max
));
274 /* Return a relation that has uniform output dimensions. */
276 __isl_give isl_union_map
*
277 extend_schedule (__isl_take isl_union_map
*x
)
281 struct extend_schedule_str str
;
283 res
= isl_union_map_foreach_map (x
, max_number_of_out_dimensions
, (void *) &max
);
284 gcc_assert (res
== 0);
287 str
.umap
= isl_union_map_empty (isl_union_map_get_space (x
));
288 res
= isl_union_map_foreach_map (x
, extend_schedule_1
, (void *) &str
);
289 gcc_assert (res
== 0);
291 isl_union_map_free (x
);
295 /* Applies SCHEDULE to the in and out dimensions of the dependences
296 DEPS and return the resulting relation. */
299 apply_schedule_on_deps (__isl_keep isl_union_map
*schedule
,
300 __isl_keep isl_union_map
*deps
)
303 isl_union_map
*ux
, *trans
;
305 trans
= isl_union_map_copy (schedule
);
306 trans
= extend_schedule (trans
);
307 ux
= isl_union_map_copy (deps
);
308 ux
= isl_union_map_apply_domain (ux
, isl_union_map_copy (trans
));
309 ux
= isl_union_map_apply_range (ux
, trans
);
310 if (isl_union_map_is_empty (ux
))
312 isl_union_map_free (ux
);
315 x
= isl_map_from_union_map (ux
);
320 /* Return true when SCHEDULE does not violate the data DEPS: that is
321 when the intersection of LEX with the DEPS transformed by SCHEDULE
322 is empty. LEX is the relation in which the outputs occur before
326 no_violations (__isl_keep isl_union_map
*schedule
,
327 __isl_keep isl_union_map
*deps
)
333 if (isl_union_map_is_empty (deps
))
336 x
= apply_schedule_on_deps (schedule
, deps
);
337 space
= isl_map_get_space (x
);
338 space
= isl_space_range (space
);
339 lex
= isl_map_lex_ge (space
);
340 x
= isl_map_intersect (x
, lex
);
341 res
= isl_map_is_empty (x
);
347 /* Return true when DEPS is non empty and the intersection of LEX with
348 the DEPS transformed by SCHEDULE is non empty. LEX is the relation
349 in which all the inputs before DEPTH occur at the same time as the
350 output, and the input at DEPTH occurs before output. */
353 carries_deps (__isl_keep isl_union_map
*schedule
,
354 __isl_keep isl_union_map
*deps
,
361 isl_constraint
*ineq
;
363 if (isl_union_map_is_empty (deps
))
366 x
= apply_schedule_on_deps (schedule
, deps
);
369 space
= isl_map_get_space (x
);
370 space
= isl_space_range (space
);
371 lex
= isl_map_lex_le (space
);
372 space
= isl_map_get_space (x
);
373 ineq
= isl_inequality_alloc (isl_local_space_from_space (space
));
375 for (i
= 0; i
< depth
- 1; i
++)
376 lex
= isl_map_equate (lex
, isl_dim_in
, i
, isl_dim_out
, i
);
379 ineq
= isl_constraint_set_coefficient_si (ineq
, isl_dim_out
, depth
- 1, 1);
380 ineq
= isl_constraint_set_coefficient_si (ineq
, isl_dim_in
, depth
- 1, -1);
381 ineq
= isl_constraint_set_constant_si (ineq
, -1);
382 lex
= isl_map_add_constraint (lex
, ineq
);
383 x
= isl_map_intersect (x
, lex
);
384 res
= !isl_map_is_empty (x
);
390 /* Subtract from the RAW, WAR, and WAW dependences those relations
391 that have been marked as belonging to an associative commutative
395 subtract_commutative_associative_deps (scop_p scop
,
397 isl_union_map
*original
,
398 isl_union_map
**must_raw
,
399 isl_union_map
**may_raw
,
400 isl_union_map
**must_raw_no_source
,
401 isl_union_map
**may_raw_no_source
,
402 isl_union_map
**must_war
,
403 isl_union_map
**may_war
,
404 isl_union_map
**must_war_no_source
,
405 isl_union_map
**may_war_no_source
,
406 isl_union_map
**must_waw
,
407 isl_union_map
**may_waw
,
408 isl_union_map
**must_waw_no_source
,
409 isl_union_map
**may_waw_no_source
)
414 isl_space
*space
= isl_set_get_space (scop
->context
);
416 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
417 if (PBB_IS_REDUCTION (pbb
))
420 isl_union_map
*r
= isl_union_map_empty (isl_space_copy (space
));
421 isl_union_map
*must_w
= isl_union_map_empty (isl_space_copy (space
));
422 isl_union_map
*may_w
= isl_union_map_empty (isl_space_copy (space
));
423 isl_union_map
*all_w
;
424 isl_union_map
*empty
;
425 isl_union_map
*x_must_raw
;
426 isl_union_map
*x_may_raw
;
427 isl_union_map
*x_must_raw_no_source
;
428 isl_union_map
*x_may_raw_no_source
;
429 isl_union_map
*x_must_war
;
430 isl_union_map
*x_may_war
;
431 isl_union_map
*x_must_war_no_source
;
432 isl_union_map
*x_may_war_no_source
;
433 isl_union_map
*x_must_waw
;
434 isl_union_map
*x_may_waw
;
435 isl_union_map
*x_must_waw_no_source
;
436 isl_union_map
*x_may_waw_no_source
;
438 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
439 if (pdr_read_p (pdr
))
440 r
= isl_union_map_add_map (r
, add_pdr_constraints (pdr
, pbb
));
442 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
443 if (pdr_write_p (pdr
))
444 must_w
= isl_union_map_add_map (must_w
,
445 add_pdr_constraints (pdr
, pbb
));
447 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
448 if (pdr_may_write_p (pdr
))
449 may_w
= isl_union_map_add_map (may_w
,
450 add_pdr_constraints (pdr
, pbb
));
452 all_w
= isl_union_map_union
453 (isl_union_map_copy (must_w
), isl_union_map_copy (may_w
));
454 empty
= isl_union_map_empty (isl_union_map_get_space (all_w
));
456 res
= isl_union_map_compute_flow (isl_union_map_copy (r
),
457 isl_union_map_copy (must_w
),
458 isl_union_map_copy (may_w
),
459 isl_union_map_copy (original
),
460 &x_must_raw
, &x_may_raw
,
461 &x_must_raw_no_source
,
462 &x_may_raw_no_source
);
463 gcc_assert (res
== 0);
464 res
= isl_union_map_compute_flow (isl_union_map_copy (all_w
),
466 isl_union_map_copy (original
),
467 &x_must_war
, &x_may_war
,
468 &x_must_war_no_source
,
469 &x_may_war_no_source
);
470 gcc_assert (res
== 0);
471 res
= isl_union_map_compute_flow (all_w
, must_w
, may_w
,
472 isl_union_map_copy (original
),
473 &x_must_waw
, &x_may_waw
,
474 &x_must_waw_no_source
,
475 &x_may_waw_no_source
);
476 gcc_assert (res
== 0);
479 *must_raw
= isl_union_map_subtract (*must_raw
, x_must_raw
);
481 isl_union_map_free (x_must_raw
);
484 *may_raw
= isl_union_map_subtract (*may_raw
, x_may_raw
);
486 isl_union_map_free (x_may_raw
);
488 if (must_raw_no_source
)
489 *must_raw_no_source
= isl_union_map_subtract (*must_raw_no_source
,
490 x_must_raw_no_source
);
492 isl_union_map_free (x_must_raw_no_source
);
494 if (may_raw_no_source
)
495 *may_raw_no_source
= isl_union_map_subtract (*may_raw_no_source
,
496 x_may_raw_no_source
);
498 isl_union_map_free (x_may_raw_no_source
);
501 *must_war
= isl_union_map_subtract (*must_war
, x_must_war
);
503 isl_union_map_free (x_must_war
);
506 *may_war
= isl_union_map_subtract (*may_war
, x_may_war
);
508 isl_union_map_free (x_may_war
);
510 if (must_war_no_source
)
511 *must_war_no_source
= isl_union_map_subtract (*must_war_no_source
,
512 x_must_war_no_source
);
514 isl_union_map_free (x_must_war_no_source
);
516 if (may_war_no_source
)
517 *may_war_no_source
= isl_union_map_subtract (*may_war_no_source
,
518 x_may_war_no_source
);
520 isl_union_map_free (x_may_war_no_source
);
523 *must_waw
= isl_union_map_subtract (*must_waw
, x_must_waw
);
525 isl_union_map_free (x_must_waw
);
528 *may_waw
= isl_union_map_subtract (*may_waw
, x_may_waw
);
530 isl_union_map_free (x_may_waw
);
532 if (must_waw_no_source
)
533 *must_waw_no_source
= isl_union_map_subtract (*must_waw_no_source
,
534 x_must_waw_no_source
);
536 isl_union_map_free (x_must_waw_no_source
);
538 if (may_waw_no_source
)
539 *may_waw_no_source
= isl_union_map_subtract (*may_waw_no_source
,
540 x_may_waw_no_source
);
542 isl_union_map_free (x_may_waw_no_source
);
545 isl_union_map_free (original
);
546 isl_space_free (space
);
549 /* Compute the original data dependences in SCOP for all the reads and
553 compute_deps (scop_p scop
, vec
<poly_bb_p
> pbbs
,
554 isl_union_map
**must_raw
,
555 isl_union_map
**may_raw
,
556 isl_union_map
**must_raw_no_source
,
557 isl_union_map
**may_raw_no_source
,
558 isl_union_map
**must_war
,
559 isl_union_map
**may_war
,
560 isl_union_map
**must_war_no_source
,
561 isl_union_map
**may_war_no_source
,
562 isl_union_map
**must_waw
,
563 isl_union_map
**may_waw
,
564 isl_union_map
**must_waw_no_source
,
565 isl_union_map
**may_waw_no_source
)
567 isl_union_map
*reads
= scop_get_reads (scop
, pbbs
);
568 isl_union_map
*must_writes
= scop_get_must_writes (scop
, pbbs
);
569 isl_union_map
*may_writes
= scop_get_may_writes (scop
, pbbs
);
570 isl_union_map
*all_writes
= isl_union_map_union
571 (isl_union_map_copy (must_writes
), isl_union_map_copy (may_writes
));
572 isl_space
*space
= isl_union_map_get_space (all_writes
);
573 isl_union_map
*empty
= isl_union_map_empty (space
);
574 isl_union_map
*original
= scop_get_original_schedule (scop
, pbbs
);
577 res
= isl_union_map_compute_flow (isl_union_map_copy (reads
),
578 isl_union_map_copy (must_writes
),
579 isl_union_map_copy (may_writes
),
580 isl_union_map_copy (original
),
581 must_raw
, may_raw
, must_raw_no_source
,
583 gcc_assert (res
== 0);
584 res
= isl_union_map_compute_flow (isl_union_map_copy (all_writes
),
586 isl_union_map_copy (original
),
587 must_war
, may_war
, must_war_no_source
,
589 gcc_assert (res
== 0);
590 res
= isl_union_map_compute_flow (all_writes
, must_writes
, may_writes
,
591 isl_union_map_copy (original
),
592 must_waw
, may_waw
, must_waw_no_source
,
594 gcc_assert (res
== 0);
596 subtract_commutative_associative_deps
597 (scop
, pbbs
, original
,
598 must_raw
, may_raw
, must_raw_no_source
, may_raw_no_source
,
599 must_war
, may_war
, must_war_no_source
, may_war_no_source
,
600 must_waw
, may_waw
, must_waw_no_source
, may_waw_no_source
);
603 /* Given a TRANSFORM, check whether it respects the original
604 dependences in SCOP. Returns true when TRANSFORM is a safe
608 transform_is_safe (scop_p scop
, isl_union_map
*transform
)
613 compute_deps (scop
, SCOP_BBS (scop
),
614 &scop
->must_raw
, &scop
->may_raw
,
615 &scop
->must_raw_no_source
, &scop
->may_raw_no_source
,
616 &scop
->must_war
, &scop
->may_war
,
617 &scop
->must_war_no_source
, &scop
->may_war_no_source
,
618 &scop
->must_waw
, &scop
->may_waw
,
619 &scop
->must_waw_no_source
, &scop
->may_waw_no_source
);
621 res
= (no_violations (transform
, scop
->must_raw
)
622 && no_violations (transform
, scop
->may_raw
)
623 && no_violations (transform
, scop
->must_war
)
624 && no_violations (transform
, scop
->may_war
)
625 && no_violations (transform
, scop
->must_waw
)
626 && no_violations (transform
, scop
->may_waw
));
628 isl_union_map_free (transform
);
632 /* Return true when the SCOP transformed schedule is correct. */
635 graphite_legal_transform (scop_p scop
)
638 isl_union_map
*transform
;
640 timevar_push (TV_GRAPHITE_DATA_DEPS
);
641 transform
= scop_get_transformed_schedule (scop
, SCOP_BBS (scop
));
642 res
= transform_is_safe (scop
, transform
);
643 timevar_pop (TV_GRAPHITE_DATA_DEPS
);