* inclhack.def (aix_complex): Redefine _Complex_I. Do not
[official-gcc.git] / gcc / graphite-dependences.c
blob59e2a0d4da23b6c589357f642c4004e2716c87a6
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)
11 any later version.
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/>. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "ggc.h"
27 #include "tree.h"
28 #include "rtl.h"
29 #include "basic-block.h"
30 #include "diagnostic.h"
31 #include "tree-flow.h"
32 #include "toplev.h"
33 #include "tree-dump.h"
34 #include "timevar.h"
35 #include "cfgloop.h"
36 #include "tree-chrec.h"
37 #include "tree-data-ref.h"
38 #include "tree-scalar-evolution.h"
39 #include "tree-pass.h"
40 #include "domwalk.h"
41 #include "pointer-set.h"
42 #include "gimple.h"
44 #ifdef HAVE_cloog
45 #include "cloog/cloog.h"
46 #include "ppl_c.h"
47 #include "sese.h"
48 #include "graphite-ppl.h"
49 #include "graphite.h"
50 #include "graphite-poly.h"
51 #include "graphite-dependences.h"
53 /* Creates a new polyhedral data reference pair and
54 returns it. Parameter SOURCE denotes a source data reference
55 while parameter SINK denotes a sink data reference. Both
56 SOURCE and SINK define a pair of references, thus they
57 define an edge in DDG (Data Dependence Graph). */
59 static poly_dr_pair_p
60 new_poly_dr_pair (poly_dr_p source,
61 poly_dr_p sink,
62 ppl_Pointset_Powerset_C_Polyhedron_t ddp)
64 poly_dr_pair_p pdrpp;
66 pdrpp = XNEW (struct poly_dr_pair);
67 pdrpp->source = source;
68 pdrpp->sink = sink;
69 pdrpp->ddp = ddp;
71 return pdrpp;
74 /* Comparison function for poly_dr_pair hash table. */
76 int
77 eq_poly_dr_pair_p (const void *pdrpp1, const void *pdrpp2)
79 const struct poly_dr_pair *p1 = (const struct poly_dr_pair *) pdrpp1;
80 const struct poly_dr_pair *p2 = (const struct poly_dr_pair *) pdrpp2;
82 return (p1->source == p2->source
83 && p1->sink == p2->sink);
86 /* Hash function for poly_dr_pair hashtable. */
88 hashval_t
89 hash_poly_dr_pair_p (const void *pdrpp)
91 const struct poly_dr_pair *p = (const struct poly_dr_pair *) pdrpp;
93 return (hashval_t) ((long) p->source + (long) p->sink);
96 /* Returns a polyhedron of dimension DIM.
98 Maps the dimensions [0, ..., cut - 1] of polyhedron P to OFFSET0
99 and the dimensions [cut, ..., nb_dim] to DIM - GDIM. */
101 static ppl_Pointset_Powerset_C_Polyhedron_t
102 map_into_dep_poly (graphite_dim_t dim, graphite_dim_t gdim,
103 ppl_Pointset_Powerset_C_Polyhedron_t p,
104 graphite_dim_t cut,
105 graphite_dim_t offset)
107 ppl_Pointset_Powerset_C_Polyhedron_t res;
109 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
110 (&res, p);
111 ppl_insert_dimensions_pointset (res, 0, offset);
112 ppl_insert_dimensions_pointset (res, offset + cut,
113 dim - offset - cut - gdim);
115 return res;
118 /* Swap [cut0, ..., cut1] to the end of DR: "a CUT0 b CUT1 c" is
119 transformed into "a CUT0 c CUT1' b"
121 Add NB0 zeros before "a": "00...0 a CUT0 c CUT1' b"
122 Add NB1 zeros between "a" and "c": "00...0 a 00...0 c CUT1' b"
123 Add DIM - NB0 - NB1 - PDIM zeros between "c" and "b":
124 "00...0 a 00...0 c 00...0 b". */
126 static ppl_Pointset_Powerset_C_Polyhedron_t
127 map_dr_into_dep_poly (graphite_dim_t dim,
128 ppl_Pointset_Powerset_C_Polyhedron_t dr,
129 graphite_dim_t cut0, graphite_dim_t cut1,
130 graphite_dim_t nb0, graphite_dim_t nb1)
132 ppl_dimension_type pdim;
133 ppl_dimension_type *map;
134 ppl_Pointset_Powerset_C_Polyhedron_t res;
135 ppl_dimension_type i;
137 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
138 (&res, dr);
139 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (res, &pdim);
141 map = (ppl_dimension_type *) XNEWVEC (ppl_dimension_type, pdim);
143 /* First mapping: move 'g' vector to right position. */
144 for (i = 0; i < cut0; i++)
145 map[i] = i;
147 for (i = cut0; i < cut1; i++)
148 map[i] = pdim - cut1 + i;
150 for (i = cut1; i < pdim; i++)
151 map[i] = cut0 + i - cut1;
153 ppl_Pointset_Powerset_C_Polyhedron_map_space_dimensions (res, map, pdim);
154 free (map);
156 /* After swapping 's' and 'g' vectors, we have to update a new cut. */
157 cut1 = pdim - cut1 + cut0;
159 ppl_insert_dimensions_pointset (res, 0, nb0);
160 ppl_insert_dimensions_pointset (res, nb0 + cut0, nb1);
161 ppl_insert_dimensions_pointset (res, nb0 + nb1 + cut1,
162 dim - nb0 - nb1 - pdim);
164 return res;
167 /* Builds a constraints of the form "POS1 - POS2 CSTR_TYPE C" */
169 static ppl_Constraint_t
170 build_pairwise_constraint (graphite_dim_t dim,
171 graphite_dim_t pos1, graphite_dim_t pos2,
172 int c, enum ppl_enum_Constraint_Type cstr_type)
174 ppl_Linear_Expression_t expr;
175 ppl_Constraint_t cstr;
176 ppl_Coefficient_t coef;
177 Value v, v_op, v_c;
179 value_init (v);
180 value_init (v_op);
181 value_init (v_c);
183 value_set_si (v, 1);
184 value_set_si (v_op, -1);
185 value_set_si (v_c, c);
187 ppl_new_Coefficient (&coef);
188 ppl_new_Linear_Expression_with_dimension (&expr, dim);
190 ppl_assign_Coefficient_from_mpz_t (coef, v);
191 ppl_Linear_Expression_add_to_coefficient (expr, pos1, coef);
192 ppl_assign_Coefficient_from_mpz_t (coef, v_op);
193 ppl_Linear_Expression_add_to_coefficient (expr, pos2, coef);
194 ppl_assign_Coefficient_from_mpz_t (coef, v_c);
195 ppl_Linear_Expression_add_to_inhomogeneous (expr, coef);
197 ppl_new_Constraint (&cstr, expr, cstr_type);
199 ppl_delete_Linear_Expression (expr);
200 ppl_delete_Coefficient (coef);
201 value_clear (v);
202 value_clear (v_op);
203 value_clear (v_c);
205 return cstr;
208 /* Builds subscript equality constraints. */
210 static ppl_Pointset_Powerset_C_Polyhedron_t
211 dr_equality_constraints (graphite_dim_t dim,
212 graphite_dim_t pos, graphite_dim_t nb_subscripts)
214 ppl_Polyhedron_t subscript_equalities;
215 ppl_Pointset_Powerset_C_Polyhedron_t res;
216 Value v, v_op;
217 graphite_dim_t i;
219 value_init (v);
220 value_init (v_op);
221 value_set_si (v, 1);
222 value_set_si (v_op, -1);
224 ppl_new_C_Polyhedron_from_space_dimension (&subscript_equalities, dim, 0);
225 for (i = 0; i < nb_subscripts; i++)
227 ppl_Linear_Expression_t expr;
228 ppl_Constraint_t cstr;
229 ppl_Coefficient_t coef;
231 ppl_new_Coefficient (&coef);
232 ppl_new_Linear_Expression_with_dimension (&expr, dim);
234 ppl_assign_Coefficient_from_mpz_t (coef, v);
235 ppl_Linear_Expression_add_to_coefficient (expr, pos + i, coef);
236 ppl_assign_Coefficient_from_mpz_t (coef, v_op);
237 ppl_Linear_Expression_add_to_coefficient (expr, pos + i + nb_subscripts,
238 coef);
240 ppl_new_Constraint (&cstr, expr, PPL_CONSTRAINT_TYPE_EQUAL);
241 ppl_Polyhedron_add_constraint (subscript_equalities, cstr);
243 ppl_delete_Linear_Expression (expr);
244 ppl_delete_Constraint (cstr);
245 ppl_delete_Coefficient (coef);
248 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron
249 (&res, subscript_equalities);
250 value_clear (v);
251 value_clear (v_op);
252 ppl_delete_Polyhedron (subscript_equalities);
254 return res;
257 /* Builds scheduling equality constraints. */
259 static ppl_Pointset_Powerset_C_Polyhedron_t
260 build_pairwise_scheduling_equality (graphite_dim_t dim,
261 graphite_dim_t pos, graphite_dim_t offset)
263 ppl_Pointset_Powerset_C_Polyhedron_t res;
264 ppl_Polyhedron_t equalities;
265 ppl_Constraint_t cstr;
267 ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
269 cstr = build_pairwise_constraint (dim, pos, pos + offset, 0,
270 PPL_CONSTRAINT_TYPE_EQUAL);
271 ppl_Polyhedron_add_constraint (equalities, cstr);
272 ppl_delete_Constraint (cstr);
274 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
275 ppl_delete_Polyhedron (equalities);
276 return res;
279 /* Builds scheduling inequality constraints. */
281 static ppl_Pointset_Powerset_C_Polyhedron_t
282 build_pairwise_scheduling_inequality (graphite_dim_t dim,
283 graphite_dim_t pos,
284 graphite_dim_t offset,
285 bool direction)
287 ppl_Pointset_Powerset_C_Polyhedron_t res;
288 ppl_Polyhedron_t equalities;
289 ppl_Constraint_t cstr;
291 ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
293 if (direction)
294 cstr = build_pairwise_constraint (dim, pos, pos + offset, -1,
295 PPL_CONSTRAINT_TYPE_GREATER_OR_EQUAL);
296 else
297 cstr = build_pairwise_constraint (dim, pos, pos + offset, 1,
298 PPL_CONSTRAINT_TYPE_LESS_OR_EQUAL);
300 ppl_Polyhedron_add_constraint (equalities, cstr);
301 ppl_delete_Constraint (cstr);
303 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
304 ppl_delete_Polyhedron (equalities);
305 return res;
308 /* Returns true when adding the lexicographical constraints at level I
309 to the RES dependence polyhedron returns an empty polyhedron. */
311 static bool
312 lexicographically_gt_p (ppl_Pointset_Powerset_C_Polyhedron_t res,
313 graphite_dim_t dim,
314 graphite_dim_t offset,
315 bool direction, graphite_dim_t i)
317 ppl_Pointset_Powerset_C_Polyhedron_t ineq;
318 bool empty_p;
320 ineq = build_pairwise_scheduling_inequality (dim, i, offset,
321 direction);
322 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (ineq, res);
323 empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (ineq);
324 if (!empty_p)
325 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, ineq);
326 ppl_delete_Pointset_Powerset_C_Polyhedron (ineq);
328 return !empty_p;
331 /* Build the precedence constraints for the lexicographical comparison
332 of time vectors RES following the lexicographical order. */
334 static void
335 build_lexicographically_gt_constraint (ppl_Pointset_Powerset_C_Polyhedron_t *res,
336 graphite_dim_t dim,
337 graphite_dim_t tdim1,
338 graphite_dim_t offset,
339 bool direction)
341 graphite_dim_t i;
343 if (lexicographically_gt_p (*res, dim, offset, direction, 0))
344 return;
346 for (i = 0; i < tdim1 - 1; i++)
348 ppl_Pointset_Powerset_C_Polyhedron_t sceq;
350 sceq = build_pairwise_scheduling_equality (dim, i, offset);
351 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (*res, sceq);
352 ppl_delete_Pointset_Powerset_C_Polyhedron (sceq);
354 if (lexicographically_gt_p (*res, dim, offset, direction, i + 1))
355 return;
358 if (i == tdim1 - 1)
360 ppl_delete_Pointset_Powerset_C_Polyhedron (*res);
361 ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (res, dim, 1);
365 /* Build the dependence polyhedron for data references PDR1 and PDR2. */
367 static ppl_Pointset_Powerset_C_Polyhedron_t
368 dependence_polyhedron_1 (poly_bb_p pbb1, poly_bb_p pbb2,
369 ppl_Pointset_Powerset_C_Polyhedron_t d1,
370 ppl_Pointset_Powerset_C_Polyhedron_t d2,
371 poly_dr_p pdr1, poly_dr_p pdr2,
372 ppl_Polyhedron_t s1, ppl_Polyhedron_t s2,
373 bool direction,
374 bool original_scattering_p)
376 scop_p scop = PBB_SCOP (pbb1);
377 graphite_dim_t tdim1 = original_scattering_p ?
378 pbb_nb_scattering_orig (pbb1) : pbb_nb_scattering_transform (pbb1);
379 graphite_dim_t tdim2 = original_scattering_p ?
380 pbb_nb_scattering_orig (pbb2) : pbb_nb_scattering_transform (pbb2);
381 graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
382 graphite_dim_t ddim2 = pbb_dim_iter_domain (pbb2);
383 graphite_dim_t sdim1 = PDR_NB_SUBSCRIPTS (pdr1) + 1;
384 graphite_dim_t gdim = scop_nb_params (scop);
385 graphite_dim_t dim1 = pdr_dim (pdr1);
386 graphite_dim_t dim2 = pdr_dim (pdr2);
387 graphite_dim_t dim = tdim1 + tdim2 + dim1 + dim2;
388 ppl_Pointset_Powerset_C_Polyhedron_t res;
389 ppl_Pointset_Powerset_C_Polyhedron_t id1, id2, isc1, isc2, idr1, idr2;
390 ppl_Pointset_Powerset_C_Polyhedron_t sc1, sc2, dreq;
392 gcc_assert (PBB_SCOP (pbb1) == PBB_SCOP (pbb2));
393 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&sc1, s1);
394 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&sc2, s2);
396 id1 = map_into_dep_poly (dim, gdim, d1, ddim1, tdim1);
397 id2 = map_into_dep_poly (dim, gdim, d2, ddim2, tdim1 + ddim1 + tdim2);
398 isc1 = map_into_dep_poly (dim, gdim, sc1, ddim1 + tdim1, 0);
399 isc2 = map_into_dep_poly (dim, gdim, sc2, ddim2 + tdim2, tdim1 + ddim1);
401 idr1 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr1), ddim1, ddim1 + gdim,
402 tdim1, tdim2 + ddim2);
403 idr2 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr2), ddim2, ddim2 + gdim,
404 tdim1 + ddim1 + tdim2, sdim1);
406 /* Now add the subscript equalities. */
407 dreq = dr_equality_constraints (dim, tdim1 + ddim1 + tdim2 + ddim2, sdim1);
409 ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&res, dim, 0);
410 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, id1);
411 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, id2);
412 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, isc1);
413 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, isc2);
414 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr1);
415 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr2);
416 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, dreq);
417 ppl_delete_Pointset_Powerset_C_Polyhedron (id1);
418 ppl_delete_Pointset_Powerset_C_Polyhedron (id2);
419 ppl_delete_Pointset_Powerset_C_Polyhedron (sc1);
420 ppl_delete_Pointset_Powerset_C_Polyhedron (sc2);
421 ppl_delete_Pointset_Powerset_C_Polyhedron (isc1);
422 ppl_delete_Pointset_Powerset_C_Polyhedron (isc2);
423 ppl_delete_Pointset_Powerset_C_Polyhedron (idr1);
424 ppl_delete_Pointset_Powerset_C_Polyhedron (idr2);
425 ppl_delete_Pointset_Powerset_C_Polyhedron (dreq);
427 if (!ppl_Pointset_Powerset_C_Polyhedron_is_empty (res))
428 build_lexicographically_gt_constraint (&res, dim, MIN (tdim1, tdim2),
429 tdim1 + ddim1, direction);
430 return res;
433 /* Build the dependence polyhedron for data references PDR1 and PDR2.
434 If possible use already cached information. */
436 static ppl_Pointset_Powerset_C_Polyhedron_t
437 dependence_polyhedron (poly_bb_p pbb1, poly_bb_p pbb2,
438 ppl_Pointset_Powerset_C_Polyhedron_t d1,
439 ppl_Pointset_Powerset_C_Polyhedron_t d2,
440 poly_dr_p pdr1, poly_dr_p pdr2,
441 ppl_Polyhedron_t s1, ppl_Polyhedron_t s2,
442 bool direction,
443 bool original_scattering_p)
445 poly_dr_pair tmp;
446 PTR *x = NULL;
447 ppl_Pointset_Powerset_C_Polyhedron_t res;
449 if (original_scattering_p)
451 tmp.source = pdr1;
452 tmp.sink = pdr2;
453 x = htab_find_slot (SCOP_ORIGINAL_PDR_PAIRS (PBB_SCOP (pbb1)),
454 &tmp, INSERT);
456 if (x && *x)
458 if (dump_file && (dump_flags & TDF_DETAILS))
459 fprintf (dump_file, "\nddp cache: hit.\n");
460 return ((poly_dr_pair *)*x)->ddp;
462 else if (dump_file && (dump_flags & TDF_DETAILS))
463 fprintf (dump_file, "\nddp cache: miss.\n");
466 res = dependence_polyhedron_1 (pbb1, pbb2, d1, d2, pdr1, pdr2,
467 s1, s2, direction, original_scattering_p);
469 if (original_scattering_p)
471 gcc_assert (x && *x == NULL);
472 *x = new_poly_dr_pair (pdr1, pdr2, res);
474 if (dump_file && (dump_flags & TDF_DETAILS))
475 fprintf (dump_file, "\nddp cache: add element.\n");
478 return res;
481 /* Returns true when the PBB_TRANSFORMED_SCATTERING functions of PBB1
482 and PBB2 respect the data dependences of PBB_ORIGINAL_SCATTERING
483 functions. */
485 static bool
486 graphite_legal_transform_dr (poly_bb_p pbb1, poly_bb_p pbb2,
487 poly_dr_p pdr1, poly_dr_p pdr2)
489 ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
490 ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
491 ppl_Polyhedron_t so1 = PBB_ORIGINAL_SCATTERING (pbb1);
492 ppl_Polyhedron_t so2 = PBB_ORIGINAL_SCATTERING (pbb2);
493 ppl_Pointset_Powerset_C_Polyhedron_t po;
495 graphite_dim_t sdim1 = PDR_NB_SUBSCRIPTS (pdr1) + 1;
496 graphite_dim_t sdim2 = PDR_NB_SUBSCRIPTS (pdr2) + 1;
498 if (sdim1 != sdim2)
499 return true;
501 po = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, so1, so2,
502 true, true);
504 if (ppl_Pointset_Powerset_C_Polyhedron_is_empty (po))
505 return true;
506 else
508 ppl_Polyhedron_t st1 = PBB_TRANSFORMED_SCATTERING (pbb1);
509 ppl_Polyhedron_t st2 = PBB_TRANSFORMED_SCATTERING (pbb2);
510 ppl_Pointset_Powerset_C_Polyhedron_t pt;
511 graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
512 graphite_dim_t otdim1 = pbb_nb_scattering_orig (pbb1);
513 graphite_dim_t otdim2 = pbb_nb_scattering_orig (pbb2);
514 graphite_dim_t ttdim1 = pbb_nb_scattering_transform (pbb1);
515 graphite_dim_t ttdim2 = pbb_nb_scattering_transform (pbb2);
516 ppl_Pointset_Powerset_C_Polyhedron_t temp;
517 ppl_dimension_type pdim;
518 bool is_empty_p;
520 /* Copy the PO polyhedron into the TEMP, so it is not destroyed.
521 Keep in mind, that PO polyhedron might be restored from the cache
522 and should not be modified! */
523 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &pdim);
524 ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&temp,
525 pdim, 0);
526 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (temp, po);
528 if (dump_file && (dump_flags & TDF_DETAILS))
529 fprintf (dump_file, "\nloop carries dependency.\n");
530 pt = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, st1, st2,
531 false, false);
533 /* Extend PO and PT to have the same dimensions. */
534 ppl_insert_dimensions_pointset (temp, otdim1, ttdim1);
535 ppl_insert_dimensions_pointset (temp, otdim1 + ttdim1 + ddim1 + otdim2,
536 ttdim2);
537 ppl_insert_dimensions_pointset (pt, 0, otdim1);
538 ppl_insert_dimensions_pointset (pt, otdim1 + ttdim1 + ddim1, otdim2);
540 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (temp, pt);
541 is_empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (temp);
543 ppl_delete_Pointset_Powerset_C_Polyhedron (temp);
544 ppl_delete_Pointset_Powerset_C_Polyhedron (pt);
545 return is_empty_p;
549 /* Iterates over the data references of PBB1 and PBB2 and detect
550 whether the transformed schedule is correct. */
552 static bool
553 graphite_legal_transform_bb (poly_bb_p pbb1, poly_bb_p pbb2)
555 int i, j;
556 poly_dr_p pdr1, pdr2;
558 for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr1); i++)
559 for (j = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), j, pdr2); j++)
560 if (!graphite_legal_transform_dr (pbb1, pbb2, pdr1, pdr2))
561 return false;
562 return true;
565 /* Iterates over the SCOP and detect whether the transformed schedule
566 is correct. */
568 bool
569 graphite_legal_transform (scop_p scop)
571 int i, j;
572 poly_bb_p pbb1, pbb2;
574 timevar_push (TV_GRAPHITE_DATA_DEPS);
576 for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
577 for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
578 if (!graphite_legal_transform_bb (pbb1, pbb2))
580 timevar_pop (TV_GRAPHITE_DATA_DEPS);
581 return false;
584 timevar_pop (TV_GRAPHITE_DATA_DEPS);
585 return true;
588 /* Remove all the dimensions except alias information at dimension
589 ALIAS_DIM. */
591 static void
592 build_alias_set_powerset (ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset,
593 ppl_dimension_type alias_dim)
595 ppl_dimension_type *ds;
596 ppl_dimension_type access_dim;
597 unsigned i, pos = 0;
599 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (alias_powerset,
600 &access_dim);
601 ds = XNEWVEC (ppl_dimension_type, access_dim-1);
602 for (i = 0; i < access_dim; i++)
604 if (i == alias_dim)
605 continue;
607 ds[pos] = i;
608 pos++;
611 ppl_Pointset_Powerset_C_Polyhedron_remove_space_dimensions (alias_powerset,
613 access_dim - 1);
614 free (ds);
617 /* Return true when PDR1 and PDR2 may alias. */
619 static bool
620 poly_drs_may_alias_p (poly_dr_p pdr1, poly_dr_p pdr2)
622 ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset1, alias_powerset2;
623 ppl_Pointset_Powerset_C_Polyhedron_t accesses1 = PDR_ACCESSES (pdr1);
624 ppl_Pointset_Powerset_C_Polyhedron_t accesses2 = PDR_ACCESSES (pdr2);
625 ppl_dimension_type alias_dim1 = pdr_alias_set_dim (pdr1);
626 ppl_dimension_type alias_dim2 = pdr_alias_set_dim (pdr2);
627 int empty_p;
629 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
630 (&alias_powerset1, accesses1);
631 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
632 (&alias_powerset2, accesses2);
634 build_alias_set_powerset (alias_powerset1, alias_dim1);
635 build_alias_set_powerset (alias_powerset2, alias_dim2);
637 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign
638 (alias_powerset1, alias_powerset2);
640 empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (alias_powerset1);
642 ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset1);
643 ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset2);
645 return !empty_p;
648 /* Returns TRUE when the dependence polyhedron between PDR1 and
649 PDR2 represents a loop carried dependence at level LEVEL. Otherwise
650 return FALSE. */
652 static bool
653 graphite_carried_dependence_level_k (poly_dr_p pdr1, poly_dr_p pdr2,
654 int level)
656 poly_bb_p pbb1 = PDR_PBB (pdr1);
657 poly_bb_p pbb2 = PDR_PBB (pdr2);
658 ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
659 ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
660 ppl_Polyhedron_t so1 = PBB_TRANSFORMED_SCATTERING (pbb1);
661 ppl_Polyhedron_t so2 = PBB_TRANSFORMED_SCATTERING (pbb2);
662 ppl_Pointset_Powerset_C_Polyhedron_t po;
663 ppl_Pointset_Powerset_C_Polyhedron_t eqpp;
664 graphite_dim_t sdim1 = PDR_NB_SUBSCRIPTS (pdr1) + 1;
665 graphite_dim_t sdim2 = PDR_NB_SUBSCRIPTS (pdr2) + 1;
666 graphite_dim_t tdim1 = pbb_nb_scattering_transform (pbb1);
667 graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
668 ppl_dimension_type dim;
669 bool empty_p;
671 if ((PDR_TYPE (pdr1) == PDR_READ && PDR_TYPE (pdr2) == PDR_READ)
672 || !poly_drs_may_alias_p (pdr1, pdr2))
673 return false;
675 if (sdim1 != sdim2)
676 return true;
678 po = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, so1, so2,
679 true, false);
680 if (ppl_Pointset_Powerset_C_Polyhedron_is_empty (po))
682 ppl_delete_Pointset_Powerset_C_Polyhedron (po);
683 return false;
686 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &dim);
687 eqpp = build_pairwise_scheduling_inequality (dim, level, tdim1 + ddim1, 1);
689 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (eqpp, po);
690 empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (eqpp);
692 ppl_delete_Pointset_Powerset_C_Polyhedron (eqpp);
693 return !empty_p;
696 /* Check data dependency between PBB1 and PBB2 at level LEVEL. */
698 bool
699 dependency_between_pbbs_p (poly_bb_p pbb1, poly_bb_p pbb2, int level)
701 int i, j;
702 poly_dr_p pdr1, pdr2;
704 timevar_push (TV_GRAPHITE_DATA_DEPS);
706 for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr1); i++)
707 for (j = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), j, pdr2); j++)
708 if (graphite_carried_dependence_level_k (pdr1, pdr2, level))
710 timevar_pop (TV_GRAPHITE_DATA_DEPS);
711 return true;
714 timevar_pop (TV_GRAPHITE_DATA_DEPS);
715 return false;
718 #endif