1 /* Data dependence analysis for Graphite.
2 Copyright (C) 2009 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/>. */
24 #include "coretypes.h"
29 #include "basic-block.h"
30 #include "diagnostic.h"
31 #include "tree-flow.h"
33 #include "tree-dump.h"
36 #include "tree-chrec.h"
37 #include "tree-data-ref.h"
38 #include "tree-scalar-evolution.h"
39 #include "tree-pass.h"
41 #include "pointer-set.h"
45 #include "cloog/cloog.h"
48 #include "graphite-ppl.h"
50 #include "graphite-poly.h"
51 #include "graphite-dependences.h"
53 /* Returns a new polyhedral Data Dependence Relation (DDR). SOURCE is
54 the source data reference, SINK is the sink data reference. When
55 the Data Dependence Polyhedron DDP is not NULL or not empty, SOURCE
56 and SINK are in dependence as described by DDP. */
59 new_poly_ddr (poly_dr_p source, poly_dr_p sink,
60 ppl_Pointset_Powerset_C_Polyhedron_t ddp,
61 bool original_scattering_p)
63 poly_ddr_p pddr = XNEW (struct poly_ddr);
65 PDDR_SOURCE (pddr) = source;
66 PDDR_SINK (pddr) = sink;
67 PDDR_DDP (pddr) = ddp;
68 PDDR_ORIGINAL_SCATTERING_P (pddr) = original_scattering_p;
70 if (!ddp || ppl_Pointset_Powerset_C_Polyhedron_is_empty (ddp))
71 PDDR_KIND (pddr) = no_dependence;
73 PDDR_KIND (pddr) = has_dependence;
78 /* Free the poly_ddr_p P. */
81 free_poly_ddr (void *p)
83 poly_ddr_p pddr = (poly_ddr_p) p;
84 ppl_delete_Pointset_Powerset_C_Polyhedron (PDDR_DDP (pddr));
88 /* Comparison function for poly_ddr hash table. */
91 eq_poly_ddr_p (const void *pddr1, const void *pddr2)
93 const struct poly_ddr *p1 = (const struct poly_ddr *) pddr1;
94 const struct poly_ddr *p2 = (const struct poly_ddr *) pddr2;
96 return (PDDR_SOURCE (p1) == PDDR_SOURCE (p2)
97 && PDDR_SINK (p1) == PDDR_SINK (p2));
100 /* Hash function for poly_ddr hashtable. */
103 hash_poly_ddr_p (const void *pddr)
105 const struct poly_ddr *p = (const struct poly_ddr *) pddr;
107 return (hashval_t) ((long) PDDR_SOURCE (p) + (long) PDDR_SINK (p));
110 /* Returns true when PDDR has no dependence. */
113 pddr_is_empty (poly_ddr_p pddr)
118 gcc_assert (PDDR_KIND (pddr) != unknown_dependence);
120 return PDDR_KIND (pddr) == no_dependence ? true : false;
123 /* Prints to FILE the layout of the dependence polyhedron of PDDR:
128 | T1 and T2 the scattering dimensions for PDDR_SOURCE and PDDR_SINK
129 | I1 and I2 the iteration domains
130 | S1 and S2 the subscripts
131 | G the global parameters. */
134 print_dependence_polyhedron_layout (FILE *file, poly_ddr_p pddr)
136 poly_dr_p pdr1 = PDDR_SOURCE (pddr);
137 poly_dr_p pdr2 = PDDR_SINK (pddr);
138 poly_bb_p pbb1 = PDR_PBB (pdr1);
139 poly_bb_p pbb2 = PDR_PBB (pdr2);
142 graphite_dim_t tdim1 = PDDR_ORIGINAL_SCATTERING_P (pddr) ?
143 pbb_nb_scattering_orig (pbb1) : pbb_nb_scattering_transform (pbb1);
144 graphite_dim_t tdim2 = PDDR_ORIGINAL_SCATTERING_P (pddr) ?
145 pbb_nb_scattering_orig (pbb2) : pbb_nb_scattering_transform (pbb2);
146 graphite_dim_t idim1 = pbb_dim_iter_domain (pbb1);
147 graphite_dim_t idim2 = pbb_dim_iter_domain (pbb2);
148 graphite_dim_t sdim1 = PDR_NB_SUBSCRIPTS (pdr1) + 1;
149 graphite_dim_t sdim2 = PDR_NB_SUBSCRIPTS (pdr2) + 1;
150 graphite_dim_t gdim = scop_nb_params (PBB_SCOP (pbb1));
152 fprintf (file, "# eq");
154 for (i = 0; i < tdim1; i++)
155 fprintf (file, " t1_%d", (int) i);
156 for (i = 0; i < idim1; i++)
157 fprintf (file, " i1_%d", (int) i);
158 for (i = 0; i < tdim2; i++)
159 fprintf (file, " t2_%d", (int) i);
160 for (i = 0; i < idim2; i++)
161 fprintf (file, " i2_%d", (int) i);
162 for (i = 0; i < sdim1; i++)
163 fprintf (file, " s1_%d", (int) i);
164 for (i = 0; i < sdim2; i++)
165 fprintf (file, " s2_%d", (int) i);
166 for (i = 0; i < gdim; i++)
167 fprintf (file, " g_%d", (int) i);
169 fprintf (file, " cst\n");
172 /* Prints to FILE the poly_ddr_p PDDR. */
175 print_pddr (FILE *file, poly_ddr_p pddr)
177 fprintf (file, "pddr (kind: ");
179 if (PDDR_KIND (pddr) == unknown_dependence)
180 fprintf (file, "unknown_dependence");
181 else if (PDDR_KIND (pddr) == no_dependence)
182 fprintf (file, "no_dependence");
183 else if (PDDR_KIND (pddr) == has_dependence)
184 fprintf (file, "has_dependence");
186 fprintf (file, "\n source ");
187 print_pdr (file, PDDR_SOURCE (pddr));
189 fprintf (file, "\n sink ");
190 print_pdr (file, PDDR_SINK (pddr));
192 if (PDDR_KIND (pddr) == has_dependence)
194 fprintf (file, "\n dependence polyhedron (\n");
195 print_dependence_polyhedron_layout (file, pddr);
196 ppl_print_powerset_matrix (file, PDDR_DDP (pddr));
197 fprintf (file, ")\n");
200 fprintf (file, ")\n");
203 /* Prints to STDERR the poly_ddr_p PDDR. */
206 debug_pddr (poly_ddr_p pddr)
208 print_pddr (stderr, pddr);
212 /* Remove all the dimensions except alias information at dimension
216 build_alias_set_powerset (ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset,
217 ppl_dimension_type alias_dim)
219 ppl_dimension_type *ds;
220 ppl_dimension_type access_dim;
223 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (alias_powerset,
225 ds = XNEWVEC (ppl_dimension_type, access_dim-1);
226 for (i = 0; i < access_dim; i++)
235 ppl_Pointset_Powerset_C_Polyhedron_remove_space_dimensions (alias_powerset,
241 /* Return true when PDR1 and PDR2 may alias. */
244 poly_drs_may_alias_p (poly_dr_p pdr1, poly_dr_p pdr2)
246 ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset1, alias_powerset2;
247 ppl_Pointset_Powerset_C_Polyhedron_t accesses1 = PDR_ACCESSES (pdr1);
248 ppl_Pointset_Powerset_C_Polyhedron_t accesses2 = PDR_ACCESSES (pdr2);
249 ppl_dimension_type alias_dim1 = pdr_alias_set_dim (pdr1);
250 ppl_dimension_type alias_dim2 = pdr_alias_set_dim (pdr2);
253 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
254 (&alias_powerset1, accesses1);
255 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
256 (&alias_powerset2, accesses2);
258 build_alias_set_powerset (alias_powerset1, alias_dim1);
259 build_alias_set_powerset (alias_powerset2, alias_dim2);
261 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign
262 (alias_powerset1, alias_powerset2);
264 empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (alias_powerset1);
266 ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset1);
267 ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset2);
272 /* Returns a polyhedron of dimension DIM.
274 Maps the dimensions [0, ..., cut - 1] of polyhedron P to OFFSET
275 and the dimensions [cut, ..., nb_dim] to DIM - GDIM. */
277 static ppl_Pointset_Powerset_C_Polyhedron_t
278 map_into_dep_poly (graphite_dim_t dim, graphite_dim_t gdim,
279 ppl_Pointset_Powerset_C_Polyhedron_t p,
281 graphite_dim_t offset)
283 ppl_Pointset_Powerset_C_Polyhedron_t res;
285 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
287 ppl_insert_dimensions_pointset (res, 0, offset);
288 ppl_insert_dimensions_pointset (res, offset + cut,
289 dim - offset - cut - gdim);
294 /* Swap [cut0, ..., cut1] to the end of DR: "a CUT0 b CUT1 c" is
295 transformed into "a CUT0 c CUT1' b"
297 Add NB0 zeros before "a": "00...0 a CUT0 c CUT1' b"
298 Add NB1 zeros between "a" and "c": "00...0 a 00...0 c CUT1' b"
299 Add DIM - NB0 - NB1 - PDIM zeros between "c" and "b":
300 "00...0 a 00...0 c 00...0 b". */
302 static ppl_Pointset_Powerset_C_Polyhedron_t
303 map_dr_into_dep_poly (graphite_dim_t dim,
304 ppl_Pointset_Powerset_C_Polyhedron_t dr,
305 graphite_dim_t cut0, graphite_dim_t cut1,
306 graphite_dim_t nb0, graphite_dim_t nb1)
308 ppl_dimension_type pdim;
309 ppl_dimension_type *map;
310 ppl_Pointset_Powerset_C_Polyhedron_t res;
311 ppl_dimension_type i;
313 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
315 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (res, &pdim);
317 map = (ppl_dimension_type *) XNEWVEC (ppl_dimension_type, pdim);
319 /* First mapping: move 'g' vector to right position. */
320 for (i = 0; i < cut0; i++)
323 for (i = cut0; i < cut1; i++)
324 map[i] = pdim - cut1 + i;
326 for (i = cut1; i < pdim; i++)
327 map[i] = cut0 + i - cut1;
329 ppl_Pointset_Powerset_C_Polyhedron_map_space_dimensions (res, map, pdim);
332 /* After swapping 's' and 'g' vectors, we have to update a new cut. */
333 cut1 = pdim - cut1 + cut0;
335 ppl_insert_dimensions_pointset (res, 0, nb0);
336 ppl_insert_dimensions_pointset (res, nb0 + cut0, nb1);
337 ppl_insert_dimensions_pointset (res, nb0 + nb1 + cut1,
338 dim - nb0 - nb1 - pdim);
343 /* Builds subscript equality constraints. */
345 static ppl_Pointset_Powerset_C_Polyhedron_t
346 dr_equality_constraints (graphite_dim_t dim,
347 graphite_dim_t pos, graphite_dim_t nb_subscripts)
349 ppl_Polyhedron_t eqs;
350 ppl_Pointset_Powerset_C_Polyhedron_t res;
353 ppl_new_C_Polyhedron_from_space_dimension (&eqs, dim, 0);
355 for (i = 0; i < nb_subscripts; i++)
357 ppl_Constraint_t cstr
358 = ppl_build_relation (dim, pos + i, pos + i + nb_subscripts,
359 0, PPL_CONSTRAINT_TYPE_EQUAL);
360 ppl_Polyhedron_add_constraint (eqs, cstr);
361 ppl_delete_Constraint (cstr);
364 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, eqs);
365 ppl_delete_Polyhedron (eqs);
369 /* Builds scheduling inequality constraints: when DIRECTION is
370 1 builds a GE constraint,
371 0 builds an EQ constraint,
372 -1 builds a LE constraint. */
374 static ppl_Pointset_Powerset_C_Polyhedron_t
375 build_pairwise_scheduling (graphite_dim_t dim,
377 graphite_dim_t offset,
380 ppl_Pointset_Powerset_C_Polyhedron_t res;
381 ppl_Polyhedron_t equalities;
382 ppl_Constraint_t cstr;
384 ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
389 cstr = ppl_build_relation (dim, pos, pos + offset, 1,
390 PPL_CONSTRAINT_TYPE_LESS_OR_EQUAL);
394 cstr = ppl_build_relation (dim, pos, pos + offset, 0,
395 PPL_CONSTRAINT_TYPE_EQUAL);
399 cstr = ppl_build_relation (dim, pos, pos + offset, -1,
400 PPL_CONSTRAINT_TYPE_GREATER_OR_EQUAL);
407 ppl_Polyhedron_add_constraint (equalities, cstr);
408 ppl_delete_Constraint (cstr);
410 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
411 ppl_delete_Polyhedron (equalities);
415 /* Add to a non empty polyhedron BAG the precedence constraints for
416 the lexicographical comparison of time vectors in BAG following the
417 lexicographical order. DIM is the dimension of the polyhedron BAG.
418 TDIM is the number of loops common to the two statements that are
419 compared lexicographically, i.e. the number of loops containing
420 both statements. OFFSET is the number of dimensions needed to
421 represent the first statement, i.e. dimT1 + dimI1 in the layout of
422 the BAG polyhedron: T1|I1|T2|I2|S1|S2|G. When DIRECTION is set to
423 1, compute the direct dependence from PDR1 to PDR2, and when
424 DIRECTION is -1, compute the reversed dependence relation, from
427 static ppl_Pointset_Powerset_C_Polyhedron_t
428 build_lexicographical_constraint (ppl_Pointset_Powerset_C_Polyhedron_t bag,
431 graphite_dim_t offset,
435 ppl_Pointset_Powerset_C_Polyhedron_t res, lex;
437 ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&res, dim, 1);
439 lex = build_pairwise_scheduling (dim, 0, offset, direction);
440 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (lex, bag);
442 if (!ppl_Pointset_Powerset_C_Polyhedron_is_empty (lex))
443 ppl_Pointset_Powerset_C_Polyhedron_upper_bound_assign (res, lex);
445 ppl_delete_Pointset_Powerset_C_Polyhedron (lex);
447 for (i = 0; i < tdim - 1; i++)
449 ppl_Pointset_Powerset_C_Polyhedron_t sceq;
451 sceq = build_pairwise_scheduling (dim, i, offset, 0);
452 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (bag, sceq);
453 ppl_delete_Pointset_Powerset_C_Polyhedron (sceq);
455 lex = build_pairwise_scheduling (dim, i + 1, offset, direction);
456 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (lex, bag);
458 if (!ppl_Pointset_Powerset_C_Polyhedron_is_empty (lex))
459 ppl_Pointset_Powerset_C_Polyhedron_upper_bound_assign (res, lex);
461 ppl_delete_Pointset_Powerset_C_Polyhedron (lex);
467 /* Build the dependence polyhedron for data references PDR1 and PDR2.
468 The layout of the dependence polyhedron is:
473 | T1 and T2 the scattering dimensions for PDR1 and PDR2
474 | I1 and I2 the iteration domains
475 | S1 and S2 the subscripts
476 | G the global parameters.
478 When DIRECTION is set to 1, compute the direct dependence from PDR1
479 to PDR2, and when DIRECTION is -1, compute the reversed dependence
480 relation, from PDR2 to PDR1. */
482 static ppl_Pointset_Powerset_C_Polyhedron_t
483 dependence_polyhedron_1 (poly_dr_p pdr1, poly_dr_p pdr2,
484 int direction, bool original_scattering_p)
486 poly_bb_p pbb1 = PDR_PBB (pdr1);
487 poly_bb_p pbb2 = PDR_PBB (pdr2);
488 scop_p scop = PBB_SCOP (pbb1);
489 ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
490 ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
491 graphite_dim_t tdim1 = original_scattering_p ?
492 pbb_nb_scattering_orig (pbb1) : pbb_nb_scattering_transform (pbb1);
493 graphite_dim_t tdim2 = original_scattering_p ?
494 pbb_nb_scattering_orig (pbb2) : pbb_nb_scattering_transform (pbb2);
495 ppl_Polyhedron_t scat1 = original_scattering_p ?
496 PBB_ORIGINAL_SCATTERING (pbb1) : PBB_TRANSFORMED_SCATTERING (pbb1);
497 ppl_Polyhedron_t scat2 = original_scattering_p ?
498 PBB_ORIGINAL_SCATTERING (pbb2) : PBB_TRANSFORMED_SCATTERING (pbb2);
499 graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
500 graphite_dim_t ddim2 = pbb_dim_iter_domain (pbb2);
501 graphite_dim_t sdim1 = PDR_NB_SUBSCRIPTS (pdr1) + 1;
502 graphite_dim_t gdim = scop_nb_params (scop);
503 graphite_dim_t dim1 = pdr_dim (pdr1);
504 graphite_dim_t dim2 = pdr_dim (pdr2);
505 graphite_dim_t dim = tdim1 + tdim2 + dim1 + dim2 - gdim;
506 ppl_Pointset_Powerset_C_Polyhedron_t res;
507 ppl_Pointset_Powerset_C_Polyhedron_t id1, id2, isc1, isc2, idr1, idr2;
508 ppl_Pointset_Powerset_C_Polyhedron_t sc1, sc2, dreq;
509 ppl_Pointset_Powerset_C_Polyhedron_t context;
511 gcc_assert (PBB_SCOP (pbb1) == PBB_SCOP (pbb2));
513 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
514 (&context, SCOP_CONTEXT (scop));
515 ppl_insert_dimensions_pointset (context, 0, dim - gdim);
517 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&sc1, scat1);
518 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&sc2, scat2);
520 id1 = map_into_dep_poly (dim, gdim, d1, ddim1, tdim1);
521 id2 = map_into_dep_poly (dim, gdim, d2, ddim2, tdim1 + ddim1 + tdim2);
522 isc1 = map_into_dep_poly (dim, gdim, sc1, ddim1 + tdim1, 0);
523 isc2 = map_into_dep_poly (dim, gdim, sc2, ddim2 + tdim2, tdim1 + ddim1);
525 idr1 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr1), ddim1, ddim1 + gdim,
526 tdim1, tdim2 + ddim2);
527 idr2 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr2), ddim2, ddim2 + gdim,
528 tdim1 + ddim1 + tdim2, sdim1);
530 /* Now add the subscript equalities. */
531 dreq = dr_equality_constraints (dim, tdim1 + ddim1 + tdim2 + ddim2, sdim1);
533 ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&res, dim, 0);
534 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, context);
535 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, id1);
536 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, id2);
537 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, isc1);
538 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, isc2);
539 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr1);
540 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr2);
541 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, dreq);
542 ppl_delete_Pointset_Powerset_C_Polyhedron (context);
543 ppl_delete_Pointset_Powerset_C_Polyhedron (id1);
544 ppl_delete_Pointset_Powerset_C_Polyhedron (id2);
545 ppl_delete_Pointset_Powerset_C_Polyhedron (sc1);
546 ppl_delete_Pointset_Powerset_C_Polyhedron (sc2);
547 ppl_delete_Pointset_Powerset_C_Polyhedron (isc1);
548 ppl_delete_Pointset_Powerset_C_Polyhedron (isc2);
549 ppl_delete_Pointset_Powerset_C_Polyhedron (idr1);
550 ppl_delete_Pointset_Powerset_C_Polyhedron (idr2);
551 ppl_delete_Pointset_Powerset_C_Polyhedron (dreq);
553 if (!ppl_Pointset_Powerset_C_Polyhedron_is_empty (res))
555 ppl_Pointset_Powerset_C_Polyhedron_t lex =
556 build_lexicographical_constraint (res, dim, MIN (tdim1, tdim2),
557 tdim1 + ddim1, direction);
558 ppl_delete_Pointset_Powerset_C_Polyhedron (res);
565 /* Build the dependence polyhedron for data references PDR1 and PDR2.
566 If possible use already cached information.
568 When DIRECTION is set to 1, compute the direct dependence from PDR1
569 to PDR2, and when DIRECTION is -1, compute the reversed dependence
570 relation, from PDR2 to PDR1. */
573 dependence_polyhedron (poly_dr_p pdr1, poly_dr_p pdr2,
574 int direction, bool original_scattering_p)
578 ppl_Pointset_Powerset_C_Polyhedron_t ddp;
580 /* Return the PDDR from the cache if it already has been computed. */
581 if (original_scattering_p)
584 scop_p scop = PBB_SCOP (PDR_PBB (pdr1));
588 x = htab_find_slot (SCOP_ORIGINAL_PDDRS (scop),
592 return (poly_ddr_p) *x;
595 if ((pdr_read_p (pdr1) && pdr_read_p (pdr2))
596 || PDR_BASE_OBJECT_SET (pdr1) != PDR_BASE_OBJECT_SET (pdr2)
597 || PDR_NB_SUBSCRIPTS (pdr1) != PDR_NB_SUBSCRIPTS (pdr2)
598 || !poly_drs_may_alias_p (pdr1, pdr2))
601 ddp = dependence_polyhedron_1 (pdr1, pdr2, direction,
602 original_scattering_p);
604 res = new_poly_ddr (pdr1, pdr2, ddp, original_scattering_p);
606 if (!(pdr_read_p (pdr1) && pdr_read_p (pdr2))
607 && PDR_BASE_OBJECT_SET (pdr1) != PDR_BASE_OBJECT_SET (pdr2)
608 && poly_drs_may_alias_p (pdr1, pdr2))
609 PDDR_KIND (res) = unknown_dependence;
611 if (original_scattering_p)
617 /* Return true when the data dependence relation between the data
618 references PDR1 belonging to PBB1 and PDR2 is part of a
622 reduction_dr_1 (poly_bb_p pbb1, poly_dr_p pdr1, poly_dr_p pdr2)
627 for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr); i++)
628 if (PDR_TYPE (pdr) == PDR_WRITE)
631 return same_pdr_p (pdr, pdr1) && same_pdr_p (pdr, pdr2);
634 /* Return true when the data dependence relation between the data
635 references PDR1 belonging to PBB1 and PDR2 belonging to PBB2 is
636 part of a reduction. */
639 reduction_dr_p (poly_dr_p pdr1, poly_dr_p pdr2)
641 poly_bb_p pbb1 = PDR_PBB (pdr1);
642 poly_bb_p pbb2 = PDR_PBB (pdr2);
644 if (PBB_IS_REDUCTION (pbb1))
645 return reduction_dr_1 (pbb1, pdr1, pdr2);
647 if (PBB_IS_REDUCTION (pbb2))
648 return reduction_dr_1 (pbb2, pdr2, pdr1);
653 /* Returns true when the PBB_TRANSFORMED_SCATTERING functions of PBB1
654 and PBB2 respect the data dependences of PBB_ORIGINAL_SCATTERING
658 graphite_legal_transform_dr (poly_dr_p pdr1, poly_dr_p pdr2)
660 ppl_Pointset_Powerset_C_Polyhedron_t po, pt;
661 graphite_dim_t ddim1, otdim1, otdim2, ttdim1, ttdim2;
662 ppl_Pointset_Powerset_C_Polyhedron_t po_temp;
663 ppl_dimension_type pdim;
665 poly_ddr_p opddr, tpddr;
666 poly_bb_p pbb1, pbb2;
668 if (reduction_dr_p (pdr1, pdr2))
671 /* We build the reverse dependence relation for the transformed
672 scattering, such that when we intersect it with the original PO,
673 we get an empty intersection when the transform is legal:
674 i.e. the transform should reverse no dependences, and so PT, the
675 reversed transformed PDDR, should have no constraint from PO. */
676 opddr = dependence_polyhedron (pdr1, pdr2, 1, true);
678 if (PDDR_KIND (opddr) == unknown_dependence)
681 /* There are no dependences between PDR1 and PDR2 in the original
682 version of the program, or after the transform, so the
683 transform is legal. */
684 if (pddr_is_empty (opddr))
687 tpddr = dependence_polyhedron (pdr1, pdr2, -1, false);
689 if (PDDR_KIND (tpddr) == unknown_dependence)
691 free_poly_ddr (tpddr);
695 if (pddr_is_empty (tpddr))
697 free_poly_ddr (tpddr);
701 po = PDDR_DDP (opddr);
702 pt = PDDR_DDP (tpddr);
704 /* Copy PO into PO_TEMP, such that PO is not destroyed. PO is
705 stored in a cache and should not be modified or freed. */
706 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &pdim);
707 ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&po_temp,
709 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (po_temp, po);
711 /* Extend PO and PT to have the same dimensions. */
712 pbb1 = PDR_PBB (pdr1);
713 pbb2 = PDR_PBB (pdr2);
714 ddim1 = pbb_dim_iter_domain (pbb1);
715 otdim1 = pbb_nb_scattering_orig (pbb1);
716 otdim2 = pbb_nb_scattering_orig (pbb2);
717 ttdim1 = pbb_nb_scattering_transform (pbb1);
718 ttdim2 = pbb_nb_scattering_transform (pbb2);
719 ppl_insert_dimensions_pointset (po_temp, otdim1, ttdim1);
720 ppl_insert_dimensions_pointset (po_temp, otdim1 + ttdim1 + ddim1 + otdim2,
722 ppl_insert_dimensions_pointset (pt, 0, otdim1);
723 ppl_insert_dimensions_pointset (pt, otdim1 + ttdim1 + ddim1, otdim2);
725 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (po_temp, pt);
726 is_empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (po_temp);
728 ppl_delete_Pointset_Powerset_C_Polyhedron (po_temp);
729 free_poly_ddr (tpddr);
731 if (dump_file && (dump_flags & TDF_DETAILS))
732 fprintf (dump_file, "\nloop carries dependency.\n");
737 /* Return true when the data dependence relation for PBB1 and PBB2 is
738 part of a reduction. */
741 reduction_ddr_p (poly_bb_p pbb1, poly_bb_p pbb2)
743 return pbb1 == pbb2 && PBB_IS_REDUCTION (pbb1);
746 /* Iterates over the data references of PBB1 and PBB2 and detect
747 whether the transformed schedule is correct. */
750 graphite_legal_transform_bb (poly_bb_p pbb1, poly_bb_p pbb2)
753 poly_dr_p pdr1, pdr2;
755 if (!PBB_PDR_DUPLICATES_REMOVED (pbb1))
756 pbb_remove_duplicate_pdrs (pbb1);
758 if (!PBB_PDR_DUPLICATES_REMOVED (pbb2))
759 pbb_remove_duplicate_pdrs (pbb2);
761 if (reduction_ddr_p (pbb1, pbb2))
764 for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr1); i++)
765 for (j = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), j, pdr2); j++)
766 if (!graphite_legal_transform_dr (pdr1, pdr2))
772 /* Iterates over the SCOP and detect whether the transformed schedule
776 graphite_legal_transform (scop_p scop)
779 poly_bb_p pbb1, pbb2;
781 timevar_push (TV_GRAPHITE_DATA_DEPS);
783 for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
784 for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
785 if (!graphite_legal_transform_bb (pbb1, pbb2))
787 timevar_pop (TV_GRAPHITE_DATA_DEPS);
791 timevar_pop (TV_GRAPHITE_DATA_DEPS);
795 /* Returns TRUE when the dependence polyhedron between PDR1 and
796 PDR2 represents a loop carried dependence at level LEVEL. */
799 graphite_carried_dependence_level_k (poly_dr_p pdr1, poly_dr_p pdr2,
802 ppl_Pointset_Powerset_C_Polyhedron_t po;
803 ppl_Pointset_Powerset_C_Polyhedron_t eqpp;
804 graphite_dim_t tdim1 = pbb_nb_scattering_transform (PDR_PBB (pdr1));
805 graphite_dim_t ddim1 = pbb_dim_iter_domain (PDR_PBB (pdr1));
806 ppl_dimension_type dim;
808 poly_ddr_p pddr = dependence_polyhedron (pdr1, pdr2, 1, false);
810 if (PDDR_KIND (pddr) == unknown_dependence)
812 free_poly_ddr (pddr);
816 if (pddr_is_empty (pddr))
818 free_poly_ddr (pddr);
822 po = PDDR_DDP (pddr);
823 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &dim);
824 eqpp = build_pairwise_scheduling (dim, level, tdim1 + ddim1, 1);
826 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (eqpp, po);
827 empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (eqpp);
829 ppl_delete_Pointset_Powerset_C_Polyhedron (eqpp);
830 free_poly_ddr (pddr);
835 /* Check data dependency between PBB1 and PBB2 at level LEVEL. */
838 dependency_between_pbbs_p (poly_bb_p pbb1, poly_bb_p pbb2, int level)
841 poly_dr_p pdr1, pdr2;
843 timevar_push (TV_GRAPHITE_DATA_DEPS);
845 for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr1); i++)
846 for (j = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), j, pdr2); j++)
847 if (graphite_carried_dependence_level_k (pdr1, pdr2, level))
849 timevar_pop (TV_GRAPHITE_DATA_DEPS);
853 timevar_pop (TV_GRAPHITE_DATA_DEPS);
857 /* Pretty print to FILE all the original data dependences of SCoP in
861 dot_original_deps_stmt_1 (FILE *file, scop_p scop)
864 poly_bb_p pbb1, pbb2;
865 poly_dr_p pdr1, pdr2;
867 for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
868 for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
870 for (k = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), k, pdr1); k++)
871 for (l = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), l, pdr2); l++)
872 if (!pddr_is_empty (dependence_polyhedron (pdr1, pdr2, 1, true)))
874 fprintf (file, "OS%d -> OS%d\n",
875 pbb_index (pbb1), pbb_index (pbb2));
882 /* Pretty print to FILE all the transformed data dependences of SCoP in
886 dot_transformed_deps_stmt_1 (FILE *file, scop_p scop)
889 poly_bb_p pbb1, pbb2;
890 poly_dr_p pdr1, pdr2;
892 for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
893 for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
895 for (k = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), k, pdr1); k++)
896 for (l = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), l, pdr2); l++)
898 poly_ddr_p pddr = dependence_polyhedron (pdr1, pdr2, 1, false);
900 if (!pddr_is_empty (pddr))
902 fprintf (file, "TS%d -> TS%d\n",
903 pbb_index (pbb1), pbb_index (pbb2));
905 free_poly_ddr (pddr);
909 free_poly_ddr (pddr);
916 /* Pretty print to FILE all the data dependences of SCoP in DOT
920 dot_deps_stmt_1 (FILE *file, scop_p scop)
922 fputs ("digraph all {\n", file);
924 dot_original_deps_stmt_1 (file, scop);
925 dot_transformed_deps_stmt_1 (file, scop);
927 fputs ("}\n\n", file);
930 /* Pretty print to FILE all the original data dependences of SCoP in
934 dot_original_deps (FILE *file, scop_p scop)
937 poly_bb_p pbb1, pbb2;
938 poly_dr_p pdr1, pdr2;
940 for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
941 for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
942 for (k = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), k, pdr1); k++)
943 for (l = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), l, pdr2); l++)
944 if (!pddr_is_empty (dependence_polyhedron (pdr1, pdr2, 1, true)))
945 fprintf (file, "OS%d_D%d -> OS%d_D%d\n",
946 pbb_index (pbb1), PDR_ID (pdr1),
947 pbb_index (pbb2), PDR_ID (pdr2));
950 /* Pretty print to FILE all the transformed data dependences of SCoP in
954 dot_transformed_deps (FILE *file, scop_p scop)
957 poly_bb_p pbb1, pbb2;
958 poly_dr_p pdr1, pdr2;
960 for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
961 for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
962 for (k = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), k, pdr1); k++)
963 for (l = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), l, pdr2); l++)
965 poly_ddr_p pddr = dependence_polyhedron (pdr1, pdr2, 1, false);
967 if (!pddr_is_empty (pddr))
968 fprintf (file, "TS%d_D%d -> TS%d_D%d\n",
969 pbb_index (pbb1), PDR_ID (pdr1),
970 pbb_index (pbb2), PDR_ID (pdr2));
972 free_poly_ddr (pddr);
976 /* Pretty print to FILE all the data dependences of SCoP in DOT
980 dot_deps_1 (FILE *file, scop_p scop)
982 fputs ("digraph all {\n", file);
984 dot_original_deps (file, scop);
985 dot_transformed_deps (file, scop);
987 fputs ("}\n\n", file);
990 /* Display all the data dependences in SCoP using dotty. */
993 dot_deps (scop_p scop)
995 /* When debugging, enable the following code. This cannot be used
996 in production compilers because it calls "system". */
999 FILE *stream = fopen ("/tmp/scopdeps.dot", "w");
1000 gcc_assert (stream);
1002 dot_deps_1 (stream, scop);
1005 x = system ("dotty /tmp/scopdeps.dot");
1007 dot_deps_1 (stderr, scop);
1011 /* Display all the statement dependences in SCoP using dotty. */
1014 dot_deps_stmt (scop_p scop)
1016 /* When debugging, enable the following code. This cannot be used
1017 in production compilers because it calls "system". */
1020 FILE *stream = fopen ("/tmp/scopdeps.dot", "w");
1021 gcc_assert (stream);
1023 dot_deps_stmt_1 (stream, scop);
1026 x = system ("dotty /tmp/scopdeps.dot");
1028 dot_deps_stmt_1 (stderr, scop);