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>
33 #include "coretypes.h"
41 #include "hard-reg-set.h"
44 #include "dominance.h"
46 #include "basic-block.h"
47 #include "tree-ssa-alias.h"
48 #include "internal-fn.h"
49 #include "gimple-expr.h"
52 #include "gimple-iterator.h"
53 #include "tree-ssa-loop.h"
54 #include "tree-pass.h"
56 #include "tree-chrec.h"
57 #include "tree-data-ref.h"
58 #include "tree-scalar-evolution.h"
62 #include "graphite-poly.h"
65 scop_get_dependences (scop_p scop
)
67 isl_union_map
*dependences
;
70 compute_deps (scop
, SCOP_BBS (scop
),
71 &scop
->must_raw
, &scop
->may_raw
,
72 &scop
->must_raw_no_source
, &scop
->may_raw_no_source
,
73 &scop
->must_war
, &scop
->may_war
,
74 &scop
->must_war_no_source
, &scop
->may_war_no_source
,
75 &scop
->must_waw
, &scop
->may_waw
,
76 &scop
->must_waw_no_source
, &scop
->may_waw_no_source
);
78 dependences
= isl_union_map_copy (scop
->must_raw
);
79 dependences
= isl_union_map_union (dependences
,
80 isl_union_map_copy (scop
->must_war
));
81 dependences
= isl_union_map_union (dependences
,
82 isl_union_map_copy (scop
->must_waw
));
83 dependences
= isl_union_map_union (dependences
,
84 isl_union_map_copy (scop
->may_raw
));
85 dependences
= isl_union_map_union (dependences
,
86 isl_union_map_copy (scop
->may_war
));
87 dependences
= isl_union_map_union (dependences
,
88 isl_union_map_copy (scop
->may_waw
));
93 /* Add the constraints from the set S to the domain of MAP. */
96 constrain_domain (isl_map
*map
, isl_set
*s
)
98 isl_space
*d
= isl_map_get_space (map
);
99 isl_id
*id
= isl_space_get_tuple_id (d
, isl_dim_in
);
101 s
= isl_set_set_tuple_id (s
, id
);
103 return isl_map_intersect_domain (map
, s
);
106 /* Constrain pdr->accesses with pdr->extent and pbb->domain. */
109 add_pdr_constraints (poly_dr_p pdr
, poly_bb_p pbb
)
111 isl_map
*x
= isl_map_intersect_range (isl_map_copy (pdr
->accesses
),
112 isl_set_copy (pdr
->extent
));
113 x
= constrain_domain (x
, isl_set_copy (pbb
->domain
));
117 /* Returns all the memory reads in SCOP. */
119 static isl_union_map
*
120 scop_get_reads (scop_p scop
, vec
<poly_bb_p
> pbbs
)
125 isl_space
*space
= isl_set_get_space (scop
->context
);
126 isl_union_map
*res
= isl_union_map_empty (space
);
128 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
130 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
131 if (pdr_read_p (pdr
))
132 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
138 /* Returns all the memory must writes in SCOP. */
140 static isl_union_map
*
141 scop_get_must_writes (scop_p scop
, vec
<poly_bb_p
> pbbs
)
146 isl_space
*space
= isl_set_get_space (scop
->context
);
147 isl_union_map
*res
= isl_union_map_empty (space
);
149 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
151 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
152 if (pdr_write_p (pdr
))
153 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
159 /* Returns all the memory may writes in SCOP. */
161 static isl_union_map
*
162 scop_get_may_writes (scop_p scop
, vec
<poly_bb_p
> pbbs
)
167 isl_space
*space
= isl_set_get_space (scop
->context
);
168 isl_union_map
*res
= isl_union_map_empty (space
);
170 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
172 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
173 if (pdr_may_write_p (pdr
))
174 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
180 /* Returns all the original schedules in SCOP. */
182 static isl_union_map
*
183 scop_get_original_schedule (scop_p scop
, vec
<poly_bb_p
> pbbs
)
187 isl_space
*space
= isl_set_get_space (scop
->context
);
188 isl_union_map
*res
= isl_union_map_empty (space
);
190 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
192 res
= isl_union_map_add_map
193 (res
, constrain_domain (isl_map_copy (pbb
->schedule
),
194 isl_set_copy (pbb
->domain
)));
200 /* Returns all the transformed schedules in SCOP. */
202 static isl_union_map
*
203 scop_get_transformed_schedule (scop_p scop
, vec
<poly_bb_p
> pbbs
)
207 isl_space
*space
= isl_set_get_space (scop
->context
);
208 isl_union_map
*res
= isl_union_map_empty (space
);
210 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
212 res
= isl_union_map_add_map
213 (res
, constrain_domain (isl_map_copy (pbb
->transformed
),
214 isl_set_copy (pbb
->domain
)));
220 /* Helper function used on each MAP of a isl_union_map. Computes the
221 maximal output dimension. */
224 max_number_of_out_dimensions (__isl_take isl_map
*map
, void *user
)
226 int global_max
= *((int *) user
);
227 isl_space
*space
= isl_map_get_space (map
);
228 int nb_out
= isl_space_dim (space
, isl_dim_out
);
230 if (global_max
< nb_out
)
231 *((int *) user
) = nb_out
;
234 isl_space_free (space
);
238 /* Extends the output dimension of MAP to MAX dimensions. */
240 static __isl_give isl_map
*
241 extend_map (__isl_take isl_map
*map
, int max
)
243 isl_space
*space
= isl_map_get_space (map
);
244 int n
= isl_space_dim (space
, isl_dim_out
);
246 isl_space_free (space
);
247 return isl_map_add_dims (map
, isl_dim_out
, max
- n
);
250 /* Structure used to pass parameters to extend_schedule_1. */
252 struct extend_schedule_str
{
257 /* Helper function for extend_schedule. */
260 extend_schedule_1 (__isl_take isl_map
*map
, void *user
)
262 struct extend_schedule_str
*str
= (struct extend_schedule_str
*) user
;
263 str
->umap
= isl_union_map_add_map (str
->umap
, extend_map (map
, str
->max
));
267 /* Return a relation that has uniform output dimensions. */
269 __isl_give isl_union_map
*
270 extend_schedule (__isl_take isl_union_map
*x
)
274 struct extend_schedule_str str
;
276 res
= isl_union_map_foreach_map (x
, max_number_of_out_dimensions
, (void *) &max
);
277 gcc_assert (res
== 0);
280 str
.umap
= isl_union_map_empty (isl_union_map_get_space (x
));
281 res
= isl_union_map_foreach_map (x
, extend_schedule_1
, (void *) &str
);
282 gcc_assert (res
== 0);
284 isl_union_map_free (x
);
288 /* Applies SCHEDULE to the in and out dimensions of the dependences
289 DEPS and return the resulting relation. */
292 apply_schedule_on_deps (__isl_keep isl_union_map
*schedule
,
293 __isl_keep isl_union_map
*deps
)
296 isl_union_map
*ux
, *trans
;
298 trans
= isl_union_map_copy (schedule
);
299 trans
= extend_schedule (trans
);
300 ux
= isl_union_map_copy (deps
);
301 ux
= isl_union_map_apply_domain (ux
, isl_union_map_copy (trans
));
302 ux
= isl_union_map_apply_range (ux
, trans
);
303 if (isl_union_map_is_empty (ux
))
305 isl_union_map_free (ux
);
308 x
= isl_map_from_union_map (ux
);
313 /* Return true when SCHEDULE does not violate the data DEPS: that is
314 when the intersection of LEX with the DEPS transformed by SCHEDULE
315 is empty. LEX is the relation in which the outputs occur before
319 no_violations (__isl_keep isl_union_map
*schedule
,
320 __isl_keep isl_union_map
*deps
)
326 if (isl_union_map_is_empty (deps
))
329 x
= apply_schedule_on_deps (schedule
, deps
);
330 space
= isl_map_get_space (x
);
331 space
= isl_space_range (space
);
332 lex
= isl_map_lex_ge (space
);
333 x
= isl_map_intersect (x
, lex
);
334 res
= isl_map_is_empty (x
);
340 /* Return true when DEPS is non empty and the intersection of LEX with
341 the DEPS transformed by SCHEDULE is non empty. LEX is the relation
342 in which all the inputs before DEPTH occur at the same time as the
343 output, and the input at DEPTH occurs before output. */
346 carries_deps (__isl_keep isl_union_map
*schedule
,
347 __isl_keep isl_union_map
*deps
,
354 isl_constraint
*ineq
;
356 if (isl_union_map_is_empty (deps
))
359 x
= apply_schedule_on_deps (schedule
, deps
);
362 space
= isl_map_get_space (x
);
363 space
= isl_space_range (space
);
364 lex
= isl_map_lex_le (space
);
365 space
= isl_map_get_space (x
);
366 ineq
= isl_inequality_alloc (isl_local_space_from_space (space
));
368 for (i
= 0; i
< depth
- 1; i
++)
369 lex
= isl_map_equate (lex
, isl_dim_in
, i
, isl_dim_out
, i
);
372 ineq
= isl_constraint_set_coefficient_si (ineq
, isl_dim_out
, depth
- 1, 1);
373 ineq
= isl_constraint_set_coefficient_si (ineq
, isl_dim_in
, depth
- 1, -1);
374 ineq
= isl_constraint_set_constant_si (ineq
, -1);
375 lex
= isl_map_add_constraint (lex
, ineq
);
376 x
= isl_map_intersect (x
, lex
);
377 res
= !isl_map_is_empty (x
);
383 /* Subtract from the RAW, WAR, and WAW dependences those relations
384 that have been marked as belonging to an associative commutative
388 subtract_commutative_associative_deps (scop_p scop
,
390 isl_union_map
*original
,
391 isl_union_map
**must_raw
,
392 isl_union_map
**may_raw
,
393 isl_union_map
**must_raw_no_source
,
394 isl_union_map
**may_raw_no_source
,
395 isl_union_map
**must_war
,
396 isl_union_map
**may_war
,
397 isl_union_map
**must_war_no_source
,
398 isl_union_map
**may_war_no_source
,
399 isl_union_map
**must_waw
,
400 isl_union_map
**may_waw
,
401 isl_union_map
**must_waw_no_source
,
402 isl_union_map
**may_waw_no_source
)
407 isl_space
*space
= isl_set_get_space (scop
->context
);
409 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
410 if (PBB_IS_REDUCTION (pbb
))
413 isl_union_map
*r
= isl_union_map_empty (isl_space_copy (space
));
414 isl_union_map
*must_w
= isl_union_map_empty (isl_space_copy (space
));
415 isl_union_map
*may_w
= isl_union_map_empty (isl_space_copy (space
));
416 isl_union_map
*all_w
;
417 isl_union_map
*empty
;
418 isl_union_map
*x_must_raw
;
419 isl_union_map
*x_may_raw
;
420 isl_union_map
*x_must_raw_no_source
;
421 isl_union_map
*x_may_raw_no_source
;
422 isl_union_map
*x_must_war
;
423 isl_union_map
*x_may_war
;
424 isl_union_map
*x_must_war_no_source
;
425 isl_union_map
*x_may_war_no_source
;
426 isl_union_map
*x_must_waw
;
427 isl_union_map
*x_may_waw
;
428 isl_union_map
*x_must_waw_no_source
;
429 isl_union_map
*x_may_waw_no_source
;
431 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
432 if (pdr_read_p (pdr
))
433 r
= isl_union_map_add_map (r
, add_pdr_constraints (pdr
, pbb
));
435 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
436 if (pdr_write_p (pdr
))
437 must_w
= isl_union_map_add_map (must_w
,
438 add_pdr_constraints (pdr
, pbb
));
440 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
441 if (pdr_may_write_p (pdr
))
442 may_w
= isl_union_map_add_map (may_w
,
443 add_pdr_constraints (pdr
, pbb
));
445 all_w
= isl_union_map_union
446 (isl_union_map_copy (must_w
), isl_union_map_copy (may_w
));
447 empty
= isl_union_map_empty (isl_union_map_get_space (all_w
));
449 res
= isl_union_map_compute_flow (isl_union_map_copy (r
),
450 isl_union_map_copy (must_w
),
451 isl_union_map_copy (may_w
),
452 isl_union_map_copy (original
),
453 &x_must_raw
, &x_may_raw
,
454 &x_must_raw_no_source
,
455 &x_may_raw_no_source
);
456 gcc_assert (res
== 0);
457 res
= isl_union_map_compute_flow (isl_union_map_copy (all_w
),
459 isl_union_map_copy (original
),
460 &x_must_war
, &x_may_war
,
461 &x_must_war_no_source
,
462 &x_may_war_no_source
);
463 gcc_assert (res
== 0);
464 res
= isl_union_map_compute_flow (all_w
, must_w
, may_w
,
465 isl_union_map_copy (original
),
466 &x_must_waw
, &x_may_waw
,
467 &x_must_waw_no_source
,
468 &x_may_waw_no_source
);
469 gcc_assert (res
== 0);
472 *must_raw
= isl_union_map_subtract (*must_raw
, x_must_raw
);
474 isl_union_map_free (x_must_raw
);
477 *may_raw
= isl_union_map_subtract (*may_raw
, x_may_raw
);
479 isl_union_map_free (x_may_raw
);
481 if (must_raw_no_source
)
482 *must_raw_no_source
= isl_union_map_subtract (*must_raw_no_source
,
483 x_must_raw_no_source
);
485 isl_union_map_free (x_must_raw_no_source
);
487 if (may_raw_no_source
)
488 *may_raw_no_source
= isl_union_map_subtract (*may_raw_no_source
,
489 x_may_raw_no_source
);
491 isl_union_map_free (x_may_raw_no_source
);
494 *must_war
= isl_union_map_subtract (*must_war
, x_must_war
);
496 isl_union_map_free (x_must_war
);
499 *may_war
= isl_union_map_subtract (*may_war
, x_may_war
);
501 isl_union_map_free (x_may_war
);
503 if (must_war_no_source
)
504 *must_war_no_source
= isl_union_map_subtract (*must_war_no_source
,
505 x_must_war_no_source
);
507 isl_union_map_free (x_must_war_no_source
);
509 if (may_war_no_source
)
510 *may_war_no_source
= isl_union_map_subtract (*may_war_no_source
,
511 x_may_war_no_source
);
513 isl_union_map_free (x_may_war_no_source
);
516 *must_waw
= isl_union_map_subtract (*must_waw
, x_must_waw
);
518 isl_union_map_free (x_must_waw
);
521 *may_waw
= isl_union_map_subtract (*may_waw
, x_may_waw
);
523 isl_union_map_free (x_may_waw
);
525 if (must_waw_no_source
)
526 *must_waw_no_source
= isl_union_map_subtract (*must_waw_no_source
,
527 x_must_waw_no_source
);
529 isl_union_map_free (x_must_waw_no_source
);
531 if (may_waw_no_source
)
532 *may_waw_no_source
= isl_union_map_subtract (*may_waw_no_source
,
533 x_may_waw_no_source
);
535 isl_union_map_free (x_may_waw_no_source
);
538 isl_union_map_free (original
);
539 isl_space_free (space
);
542 /* Compute the original data dependences in SCOP for all the reads and
546 compute_deps (scop_p scop
, vec
<poly_bb_p
> pbbs
,
547 isl_union_map
**must_raw
,
548 isl_union_map
**may_raw
,
549 isl_union_map
**must_raw_no_source
,
550 isl_union_map
**may_raw_no_source
,
551 isl_union_map
**must_war
,
552 isl_union_map
**may_war
,
553 isl_union_map
**must_war_no_source
,
554 isl_union_map
**may_war_no_source
,
555 isl_union_map
**must_waw
,
556 isl_union_map
**may_waw
,
557 isl_union_map
**must_waw_no_source
,
558 isl_union_map
**may_waw_no_source
)
560 isl_union_map
*reads
= scop_get_reads (scop
, pbbs
);
561 isl_union_map
*must_writes
= scop_get_must_writes (scop
, pbbs
);
562 isl_union_map
*may_writes
= scop_get_may_writes (scop
, pbbs
);
563 isl_union_map
*all_writes
= isl_union_map_union
564 (isl_union_map_copy (must_writes
), isl_union_map_copy (may_writes
));
565 isl_space
*space
= isl_union_map_get_space (all_writes
);
566 isl_union_map
*empty
= isl_union_map_empty (space
);
567 isl_union_map
*original
= scop_get_original_schedule (scop
, pbbs
);
570 res
= isl_union_map_compute_flow (isl_union_map_copy (reads
),
571 isl_union_map_copy (must_writes
),
572 isl_union_map_copy (may_writes
),
573 isl_union_map_copy (original
),
574 must_raw
, may_raw
, must_raw_no_source
,
576 gcc_assert (res
== 0);
577 res
= isl_union_map_compute_flow (isl_union_map_copy (all_writes
),
579 isl_union_map_copy (original
),
580 must_war
, may_war
, must_war_no_source
,
582 gcc_assert (res
== 0);
583 res
= isl_union_map_compute_flow (all_writes
, must_writes
, may_writes
,
584 isl_union_map_copy (original
),
585 must_waw
, may_waw
, must_waw_no_source
,
587 gcc_assert (res
== 0);
589 subtract_commutative_associative_deps
590 (scop
, pbbs
, original
,
591 must_raw
, may_raw
, must_raw_no_source
, may_raw_no_source
,
592 must_war
, may_war
, must_war_no_source
, may_war_no_source
,
593 must_waw
, may_waw
, must_waw_no_source
, may_waw_no_source
);
596 /* Given a TRANSFORM, check whether it respects the original
597 dependences in SCOP. Returns true when TRANSFORM is a safe
601 transform_is_safe (scop_p scop
, isl_union_map
*transform
)
606 compute_deps (scop
, SCOP_BBS (scop
),
607 &scop
->must_raw
, &scop
->may_raw
,
608 &scop
->must_raw_no_source
, &scop
->may_raw_no_source
,
609 &scop
->must_war
, &scop
->may_war
,
610 &scop
->must_war_no_source
, &scop
->may_war_no_source
,
611 &scop
->must_waw
, &scop
->may_waw
,
612 &scop
->must_waw_no_source
, &scop
->may_waw_no_source
);
614 res
= (no_violations (transform
, scop
->must_raw
)
615 && no_violations (transform
, scop
->may_raw
)
616 && no_violations (transform
, scop
->must_war
)
617 && no_violations (transform
, scop
->may_war
)
618 && no_violations (transform
, scop
->must_waw
)
619 && no_violations (transform
, scop
->may_waw
));
621 isl_union_map_free (transform
);
625 /* Return true when the SCOP transformed schedule is correct. */
628 graphite_legal_transform (scop_p scop
)
631 isl_union_map
*transform
;
633 timevar_push (TV_GRAPHITE_DATA_DEPS
);
634 transform
= scop_get_transformed_schedule (scop
, SCOP_BBS (scop
));
635 res
= transform_is_safe (scop
, transform
);
636 timevar_pop (TV_GRAPHITE_DATA_DEPS
);