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"
39 #include "fold-const.h"
42 #include "hard-reg-set.h"
45 #include "dominance.h"
47 #include "basic-block.h"
48 #include "tree-ssa-alias.h"
49 #include "internal-fn.h"
50 #include "gimple-expr.h"
53 #include "gimple-iterator.h"
54 #include "tree-ssa-loop.h"
55 #include "tree-pass.h"
57 #include "tree-chrec.h"
58 #include "tree-data-ref.h"
59 #include "tree-scalar-evolution.h"
63 #include "graphite-poly.h"
66 scop_get_dependences (scop_p scop
)
68 isl_union_map
*dependences
;
71 compute_deps (scop
, SCOP_BBS (scop
),
72 &scop
->must_raw
, &scop
->may_raw
,
73 &scop
->must_raw_no_source
, &scop
->may_raw_no_source
,
74 &scop
->must_war
, &scop
->may_war
,
75 &scop
->must_war_no_source
, &scop
->may_war_no_source
,
76 &scop
->must_waw
, &scop
->may_waw
,
77 &scop
->must_waw_no_source
, &scop
->may_waw_no_source
);
79 dependences
= isl_union_map_copy (scop
->must_raw
);
80 dependences
= isl_union_map_union (dependences
,
81 isl_union_map_copy (scop
->must_war
));
82 dependences
= isl_union_map_union (dependences
,
83 isl_union_map_copy (scop
->must_waw
));
84 dependences
= isl_union_map_union (dependences
,
85 isl_union_map_copy (scop
->may_raw
));
86 dependences
= isl_union_map_union (dependences
,
87 isl_union_map_copy (scop
->may_war
));
88 dependences
= isl_union_map_union (dependences
,
89 isl_union_map_copy (scop
->may_waw
));
94 /* Add the constraints from the set S to the domain of MAP. */
97 constrain_domain (isl_map
*map
, isl_set
*s
)
99 isl_space
*d
= isl_map_get_space (map
);
100 isl_id
*id
= isl_space_get_tuple_id (d
, isl_dim_in
);
102 s
= isl_set_set_tuple_id (s
, id
);
104 return isl_map_intersect_domain (map
, s
);
107 /* Constrain pdr->accesses with pdr->extent and pbb->domain. */
110 add_pdr_constraints (poly_dr_p pdr
, poly_bb_p pbb
)
112 isl_map
*x
= isl_map_intersect_range (isl_map_copy (pdr
->accesses
),
113 isl_set_copy (pdr
->extent
));
114 x
= constrain_domain (x
, isl_set_copy (pbb
->domain
));
118 /* Returns all the memory reads in SCOP. */
120 static isl_union_map
*
121 scop_get_reads (scop_p scop
, vec
<poly_bb_p
> pbbs
)
126 isl_space
*space
= isl_set_get_space (scop
->context
);
127 isl_union_map
*res
= isl_union_map_empty (space
);
129 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
131 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
132 if (pdr_read_p (pdr
))
133 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
139 /* Returns all the memory must writes in SCOP. */
141 static isl_union_map
*
142 scop_get_must_writes (scop_p scop
, vec
<poly_bb_p
> pbbs
)
147 isl_space
*space
= isl_set_get_space (scop
->context
);
148 isl_union_map
*res
= isl_union_map_empty (space
);
150 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
152 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
153 if (pdr_write_p (pdr
))
154 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
160 /* Returns all the memory may writes in SCOP. */
162 static isl_union_map
*
163 scop_get_may_writes (scop_p scop
, vec
<poly_bb_p
> pbbs
)
168 isl_space
*space
= isl_set_get_space (scop
->context
);
169 isl_union_map
*res
= isl_union_map_empty (space
);
171 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
173 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
174 if (pdr_may_write_p (pdr
))
175 res
= isl_union_map_add_map (res
, add_pdr_constraints (pdr
, pbb
));
181 /* Returns all the original schedules in SCOP. */
183 static isl_union_map
*
184 scop_get_original_schedule (scop_p scop
, vec
<poly_bb_p
> pbbs
)
188 isl_space
*space
= isl_set_get_space (scop
->context
);
189 isl_union_map
*res
= isl_union_map_empty (space
);
191 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
193 res
= isl_union_map_add_map
194 (res
, constrain_domain (isl_map_copy (pbb
->schedule
),
195 isl_set_copy (pbb
->domain
)));
201 /* Returns all the transformed schedules in SCOP. */
203 static isl_union_map
*
204 scop_get_transformed_schedule (scop_p scop
, vec
<poly_bb_p
> pbbs
)
208 isl_space
*space
= isl_set_get_space (scop
->context
);
209 isl_union_map
*res
= isl_union_map_empty (space
);
211 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
213 res
= isl_union_map_add_map
214 (res
, constrain_domain (isl_map_copy (pbb
->transformed
),
215 isl_set_copy (pbb
->domain
)));
221 /* Helper function used on each MAP of a isl_union_map. Computes the
222 maximal output dimension. */
225 max_number_of_out_dimensions (__isl_take isl_map
*map
, void *user
)
227 int global_max
= *((int *) user
);
228 isl_space
*space
= isl_map_get_space (map
);
229 int nb_out
= isl_space_dim (space
, isl_dim_out
);
231 if (global_max
< nb_out
)
232 *((int *) user
) = nb_out
;
235 isl_space_free (space
);
239 /* Extends the output dimension of MAP to MAX dimensions. */
241 static __isl_give isl_map
*
242 extend_map (__isl_take isl_map
*map
, int max
)
244 isl_space
*space
= isl_map_get_space (map
);
245 int n
= isl_space_dim (space
, isl_dim_out
);
247 isl_space_free (space
);
248 return isl_map_add_dims (map
, isl_dim_out
, max
- n
);
251 /* Structure used to pass parameters to extend_schedule_1. */
253 struct extend_schedule_str
{
258 /* Helper function for extend_schedule. */
261 extend_schedule_1 (__isl_take isl_map
*map
, void *user
)
263 struct extend_schedule_str
*str
= (struct extend_schedule_str
*) user
;
264 str
->umap
= isl_union_map_add_map (str
->umap
, extend_map (map
, str
->max
));
268 /* Return a relation that has uniform output dimensions. */
270 __isl_give isl_union_map
*
271 extend_schedule (__isl_take isl_union_map
*x
)
275 struct extend_schedule_str str
;
277 res
= isl_union_map_foreach_map (x
, max_number_of_out_dimensions
, (void *) &max
);
278 gcc_assert (res
== 0);
281 str
.umap
= isl_union_map_empty (isl_union_map_get_space (x
));
282 res
= isl_union_map_foreach_map (x
, extend_schedule_1
, (void *) &str
);
283 gcc_assert (res
== 0);
285 isl_union_map_free (x
);
289 /* Applies SCHEDULE to the in and out dimensions of the dependences
290 DEPS and return the resulting relation. */
293 apply_schedule_on_deps (__isl_keep isl_union_map
*schedule
,
294 __isl_keep isl_union_map
*deps
)
297 isl_union_map
*ux
, *trans
;
299 trans
= isl_union_map_copy (schedule
);
300 trans
= extend_schedule (trans
);
301 ux
= isl_union_map_copy (deps
);
302 ux
= isl_union_map_apply_domain (ux
, isl_union_map_copy (trans
));
303 ux
= isl_union_map_apply_range (ux
, trans
);
304 if (isl_union_map_is_empty (ux
))
306 isl_union_map_free (ux
);
309 x
= isl_map_from_union_map (ux
);
314 /* Return true when SCHEDULE does not violate the data DEPS: that is
315 when the intersection of LEX with the DEPS transformed by SCHEDULE
316 is empty. LEX is the relation in which the outputs occur before
320 no_violations (__isl_keep isl_union_map
*schedule
,
321 __isl_keep isl_union_map
*deps
)
327 if (isl_union_map_is_empty (deps
))
330 x
= apply_schedule_on_deps (schedule
, deps
);
331 space
= isl_map_get_space (x
);
332 space
= isl_space_range (space
);
333 lex
= isl_map_lex_ge (space
);
334 x
= isl_map_intersect (x
, lex
);
335 res
= isl_map_is_empty (x
);
341 /* Return true when DEPS is non empty and the intersection of LEX with
342 the DEPS transformed by SCHEDULE is non empty. LEX is the relation
343 in which all the inputs before DEPTH occur at the same time as the
344 output, and the input at DEPTH occurs before output. */
347 carries_deps (__isl_keep isl_union_map
*schedule
,
348 __isl_keep isl_union_map
*deps
,
355 isl_constraint
*ineq
;
357 if (isl_union_map_is_empty (deps
))
360 x
= apply_schedule_on_deps (schedule
, deps
);
363 space
= isl_map_get_space (x
);
364 space
= isl_space_range (space
);
365 lex
= isl_map_lex_le (space
);
366 space
= isl_map_get_space (x
);
367 ineq
= isl_inequality_alloc (isl_local_space_from_space (space
));
369 for (i
= 0; i
< depth
- 1; i
++)
370 lex
= isl_map_equate (lex
, isl_dim_in
, i
, isl_dim_out
, i
);
373 ineq
= isl_constraint_set_coefficient_si (ineq
, isl_dim_out
, depth
- 1, 1);
374 ineq
= isl_constraint_set_coefficient_si (ineq
, isl_dim_in
, depth
- 1, -1);
375 ineq
= isl_constraint_set_constant_si (ineq
, -1);
376 lex
= isl_map_add_constraint (lex
, ineq
);
377 x
= isl_map_intersect (x
, lex
);
378 res
= !isl_map_is_empty (x
);
384 /* Subtract from the RAW, WAR, and WAW dependences those relations
385 that have been marked as belonging to an associative commutative
389 subtract_commutative_associative_deps (scop_p scop
,
391 isl_union_map
*original
,
392 isl_union_map
**must_raw
,
393 isl_union_map
**may_raw
,
394 isl_union_map
**must_raw_no_source
,
395 isl_union_map
**may_raw_no_source
,
396 isl_union_map
**must_war
,
397 isl_union_map
**may_war
,
398 isl_union_map
**must_war_no_source
,
399 isl_union_map
**may_war_no_source
,
400 isl_union_map
**must_waw
,
401 isl_union_map
**may_waw
,
402 isl_union_map
**must_waw_no_source
,
403 isl_union_map
**may_waw_no_source
)
408 isl_space
*space
= isl_set_get_space (scop
->context
);
410 FOR_EACH_VEC_ELT (pbbs
, i
, pbb
)
411 if (PBB_IS_REDUCTION (pbb
))
414 isl_union_map
*r
= isl_union_map_empty (isl_space_copy (space
));
415 isl_union_map
*must_w
= isl_union_map_empty (isl_space_copy (space
));
416 isl_union_map
*may_w
= isl_union_map_empty (isl_space_copy (space
));
417 isl_union_map
*all_w
;
418 isl_union_map
*empty
;
419 isl_union_map
*x_must_raw
;
420 isl_union_map
*x_may_raw
;
421 isl_union_map
*x_must_raw_no_source
;
422 isl_union_map
*x_may_raw_no_source
;
423 isl_union_map
*x_must_war
;
424 isl_union_map
*x_may_war
;
425 isl_union_map
*x_must_war_no_source
;
426 isl_union_map
*x_may_war_no_source
;
427 isl_union_map
*x_must_waw
;
428 isl_union_map
*x_may_waw
;
429 isl_union_map
*x_must_waw_no_source
;
430 isl_union_map
*x_may_waw_no_source
;
432 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
433 if (pdr_read_p (pdr
))
434 r
= isl_union_map_add_map (r
, add_pdr_constraints (pdr
, pbb
));
436 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
437 if (pdr_write_p (pdr
))
438 must_w
= isl_union_map_add_map (must_w
,
439 add_pdr_constraints (pdr
, pbb
));
441 FOR_EACH_VEC_ELT (PBB_DRS (pbb
), j
, pdr
)
442 if (pdr_may_write_p (pdr
))
443 may_w
= isl_union_map_add_map (may_w
,
444 add_pdr_constraints (pdr
, pbb
));
446 all_w
= isl_union_map_union
447 (isl_union_map_copy (must_w
), isl_union_map_copy (may_w
));
448 empty
= isl_union_map_empty (isl_union_map_get_space (all_w
));
450 res
= isl_union_map_compute_flow (isl_union_map_copy (r
),
451 isl_union_map_copy (must_w
),
452 isl_union_map_copy (may_w
),
453 isl_union_map_copy (original
),
454 &x_must_raw
, &x_may_raw
,
455 &x_must_raw_no_source
,
456 &x_may_raw_no_source
);
457 gcc_assert (res
== 0);
458 res
= isl_union_map_compute_flow (isl_union_map_copy (all_w
),
460 isl_union_map_copy (original
),
461 &x_must_war
, &x_may_war
,
462 &x_must_war_no_source
,
463 &x_may_war_no_source
);
464 gcc_assert (res
== 0);
465 res
= isl_union_map_compute_flow (all_w
, must_w
, may_w
,
466 isl_union_map_copy (original
),
467 &x_must_waw
, &x_may_waw
,
468 &x_must_waw_no_source
,
469 &x_may_waw_no_source
);
470 gcc_assert (res
== 0);
473 *must_raw
= isl_union_map_subtract (*must_raw
, x_must_raw
);
475 isl_union_map_free (x_must_raw
);
478 *may_raw
= isl_union_map_subtract (*may_raw
, x_may_raw
);
480 isl_union_map_free (x_may_raw
);
482 if (must_raw_no_source
)
483 *must_raw_no_source
= isl_union_map_subtract (*must_raw_no_source
,
484 x_must_raw_no_source
);
486 isl_union_map_free (x_must_raw_no_source
);
488 if (may_raw_no_source
)
489 *may_raw_no_source
= isl_union_map_subtract (*may_raw_no_source
,
490 x_may_raw_no_source
);
492 isl_union_map_free (x_may_raw_no_source
);
495 *must_war
= isl_union_map_subtract (*must_war
, x_must_war
);
497 isl_union_map_free (x_must_war
);
500 *may_war
= isl_union_map_subtract (*may_war
, x_may_war
);
502 isl_union_map_free (x_may_war
);
504 if (must_war_no_source
)
505 *must_war_no_source
= isl_union_map_subtract (*must_war_no_source
,
506 x_must_war_no_source
);
508 isl_union_map_free (x_must_war_no_source
);
510 if (may_war_no_source
)
511 *may_war_no_source
= isl_union_map_subtract (*may_war_no_source
,
512 x_may_war_no_source
);
514 isl_union_map_free (x_may_war_no_source
);
517 *must_waw
= isl_union_map_subtract (*must_waw
, x_must_waw
);
519 isl_union_map_free (x_must_waw
);
522 *may_waw
= isl_union_map_subtract (*may_waw
, x_may_waw
);
524 isl_union_map_free (x_may_waw
);
526 if (must_waw_no_source
)
527 *must_waw_no_source
= isl_union_map_subtract (*must_waw_no_source
,
528 x_must_waw_no_source
);
530 isl_union_map_free (x_must_waw_no_source
);
532 if (may_waw_no_source
)
533 *may_waw_no_source
= isl_union_map_subtract (*may_waw_no_source
,
534 x_may_waw_no_source
);
536 isl_union_map_free (x_may_waw_no_source
);
539 isl_union_map_free (original
);
540 isl_space_free (space
);
543 /* Compute the original data dependences in SCOP for all the reads and
547 compute_deps (scop_p scop
, vec
<poly_bb_p
> pbbs
,
548 isl_union_map
**must_raw
,
549 isl_union_map
**may_raw
,
550 isl_union_map
**must_raw_no_source
,
551 isl_union_map
**may_raw_no_source
,
552 isl_union_map
**must_war
,
553 isl_union_map
**may_war
,
554 isl_union_map
**must_war_no_source
,
555 isl_union_map
**may_war_no_source
,
556 isl_union_map
**must_waw
,
557 isl_union_map
**may_waw
,
558 isl_union_map
**must_waw_no_source
,
559 isl_union_map
**may_waw_no_source
)
561 isl_union_map
*reads
= scop_get_reads (scop
, pbbs
);
562 isl_union_map
*must_writes
= scop_get_must_writes (scop
, pbbs
);
563 isl_union_map
*may_writes
= scop_get_may_writes (scop
, pbbs
);
564 isl_union_map
*all_writes
= isl_union_map_union
565 (isl_union_map_copy (must_writes
), isl_union_map_copy (may_writes
));
566 isl_space
*space
= isl_union_map_get_space (all_writes
);
567 isl_union_map
*empty
= isl_union_map_empty (space
);
568 isl_union_map
*original
= scop_get_original_schedule (scop
, pbbs
);
571 res
= isl_union_map_compute_flow (isl_union_map_copy (reads
),
572 isl_union_map_copy (must_writes
),
573 isl_union_map_copy (may_writes
),
574 isl_union_map_copy (original
),
575 must_raw
, may_raw
, must_raw_no_source
,
577 gcc_assert (res
== 0);
578 res
= isl_union_map_compute_flow (isl_union_map_copy (all_writes
),
580 isl_union_map_copy (original
),
581 must_war
, may_war
, must_war_no_source
,
583 gcc_assert (res
== 0);
584 res
= isl_union_map_compute_flow (all_writes
, must_writes
, may_writes
,
585 isl_union_map_copy (original
),
586 must_waw
, may_waw
, must_waw_no_source
,
588 gcc_assert (res
== 0);
590 subtract_commutative_associative_deps
591 (scop
, pbbs
, original
,
592 must_raw
, may_raw
, must_raw_no_source
, may_raw_no_source
,
593 must_war
, may_war
, must_war_no_source
, may_war_no_source
,
594 must_waw
, may_waw
, must_waw_no_source
, may_waw_no_source
);
597 /* Given a TRANSFORM, check whether it respects the original
598 dependences in SCOP. Returns true when TRANSFORM is a safe
602 transform_is_safe (scop_p scop
, isl_union_map
*transform
)
607 compute_deps (scop
, SCOP_BBS (scop
),
608 &scop
->must_raw
, &scop
->may_raw
,
609 &scop
->must_raw_no_source
, &scop
->may_raw_no_source
,
610 &scop
->must_war
, &scop
->may_war
,
611 &scop
->must_war_no_source
, &scop
->may_war_no_source
,
612 &scop
->must_waw
, &scop
->may_waw
,
613 &scop
->must_waw_no_source
, &scop
->may_waw_no_source
);
615 res
= (no_violations (transform
, scop
->must_raw
)
616 && no_violations (transform
, scop
->may_raw
)
617 && no_violations (transform
, scop
->must_war
)
618 && no_violations (transform
, scop
->may_war
)
619 && no_violations (transform
, scop
->must_waw
)
620 && no_violations (transform
, scop
->may_waw
));
622 isl_union_map_free (transform
);
626 /* Return true when the SCOP transformed schedule is correct. */
629 graphite_legal_transform (scop_p scop
)
632 isl_union_map
*transform
;
634 timevar_push (TV_GRAPHITE_DATA_DEPS
);
635 transform
= scop_get_transformed_schedule (scop
, SCOP_BBS (scop
));
636 res
= transform_is_safe (scop
, transform
);
637 timevar_pop (TV_GRAPHITE_DATA_DEPS
);