* gcc-plugin.h (enum plugin_event): Add PLUGIN_ALL_IPA_PASSES_START,
[official-gcc.git] / gcc / graphite-dependences.c
blob7fce3b331e7783151630ffba2e907d61accbf17f
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 /* Returns a new polyhedral Data Dependence Relation (DDR). SOURCE is
54 the source data reference, SINK is the sink data reference. SOURCE
55 and SINK define an edge in the Data Dependence Graph (DDG). */
57 static poly_ddr_p
58 new_poly_ddr (poly_dr_p source, poly_dr_p sink,
59 ppl_Pointset_Powerset_C_Polyhedron_t ddp)
61 poly_ddr_p pddr;
63 pddr = XNEW (struct poly_ddr);
64 PDDR_SOURCE (pddr) = source;
65 PDDR_SINK (pddr) = sink;
66 PDDR_DDP (pddr) = ddp;
67 PDDR_KIND (pddr) = unknown_dependence;
69 return pddr;
72 /* Free the poly_ddr_p P. */
74 void
75 free_poly_ddr (void *p)
77 poly_ddr_p pddr = (poly_ddr_p) p;
78 ppl_delete_Pointset_Powerset_C_Polyhedron (PDDR_DDP (pddr));
79 free (pddr);
82 /* Comparison function for poly_ddr hash table. */
84 int
85 eq_poly_ddr_p (const void *pddr1, const void *pddr2)
87 const struct poly_ddr *p1 = (const struct poly_ddr *) pddr1;
88 const struct poly_ddr *p2 = (const struct poly_ddr *) pddr2;
90 return (PDDR_SOURCE (p1) == PDDR_SOURCE (p2)
91 && PDDR_SINK (p1) == PDDR_SINK (p2));
94 /* Hash function for poly_ddr hashtable. */
96 hashval_t
97 hash_poly_ddr_p (const void *pddr)
99 const struct poly_ddr *p = (const struct poly_ddr *) pddr;
101 return (hashval_t) ((long) PDDR_SOURCE (p) + (long) PDDR_SINK (p));
104 /* Returns true when PDDR has no dependence. */
106 static bool
107 pddr_is_empty (poly_ddr_p pddr)
109 if (PDDR_KIND (pddr) != unknown_dependence)
110 return PDDR_KIND (pddr) == no_dependence ? true : false;
112 if (ppl_Pointset_Powerset_C_Polyhedron_is_empty (PDDR_DDP (pddr)))
114 PDDR_KIND (pddr) = no_dependence;
115 return true;
118 PDDR_KIND (pddr) = has_dependence;
119 return false;
122 /* Returns a polyhedron of dimension DIM.
124 Maps the dimensions [0, ..., cut - 1] of polyhedron P to OFFSET0
125 and the dimensions [cut, ..., nb_dim] to DIM - GDIM. */
127 static ppl_Pointset_Powerset_C_Polyhedron_t
128 map_into_dep_poly (graphite_dim_t dim, graphite_dim_t gdim,
129 ppl_Pointset_Powerset_C_Polyhedron_t p,
130 graphite_dim_t cut,
131 graphite_dim_t offset)
133 ppl_Pointset_Powerset_C_Polyhedron_t res;
135 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
136 (&res, p);
137 ppl_insert_dimensions_pointset (res, 0, offset);
138 ppl_insert_dimensions_pointset (res, offset + cut,
139 dim - offset - cut - gdim);
141 return res;
144 /* Swap [cut0, ..., cut1] to the end of DR: "a CUT0 b CUT1 c" is
145 transformed into "a CUT0 c CUT1' b"
147 Add NB0 zeros before "a": "00...0 a CUT0 c CUT1' b"
148 Add NB1 zeros between "a" and "c": "00...0 a 00...0 c CUT1' b"
149 Add DIM - NB0 - NB1 - PDIM zeros between "c" and "b":
150 "00...0 a 00...0 c 00...0 b". */
152 static ppl_Pointset_Powerset_C_Polyhedron_t
153 map_dr_into_dep_poly (graphite_dim_t dim,
154 ppl_Pointset_Powerset_C_Polyhedron_t dr,
155 graphite_dim_t cut0, graphite_dim_t cut1,
156 graphite_dim_t nb0, graphite_dim_t nb1)
158 ppl_dimension_type pdim;
159 ppl_dimension_type *map;
160 ppl_Pointset_Powerset_C_Polyhedron_t res;
161 ppl_dimension_type i;
163 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
164 (&res, dr);
165 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (res, &pdim);
167 map = (ppl_dimension_type *) XNEWVEC (ppl_dimension_type, pdim);
169 /* First mapping: move 'g' vector to right position. */
170 for (i = 0; i < cut0; i++)
171 map[i] = i;
173 for (i = cut0; i < cut1; i++)
174 map[i] = pdim - cut1 + i;
176 for (i = cut1; i < pdim; i++)
177 map[i] = cut0 + i - cut1;
179 ppl_Pointset_Powerset_C_Polyhedron_map_space_dimensions (res, map, pdim);
180 free (map);
182 /* After swapping 's' and 'g' vectors, we have to update a new cut. */
183 cut1 = pdim - cut1 + cut0;
185 ppl_insert_dimensions_pointset (res, 0, nb0);
186 ppl_insert_dimensions_pointset (res, nb0 + cut0, nb1);
187 ppl_insert_dimensions_pointset (res, nb0 + nb1 + cut1,
188 dim - nb0 - nb1 - pdim);
190 return res;
193 /* Builds a constraints of the form "POS1 - POS2 CSTR_TYPE C" */
195 static ppl_Constraint_t
196 build_pairwise_constraint (graphite_dim_t dim,
197 graphite_dim_t pos1, graphite_dim_t pos2,
198 int c, enum ppl_enum_Constraint_Type cstr_type)
200 ppl_Linear_Expression_t expr;
201 ppl_Constraint_t cstr;
202 ppl_Coefficient_t coef;
203 Value v, v_op, v_c;
205 value_init (v);
206 value_init (v_op);
207 value_init (v_c);
209 value_set_si (v, 1);
210 value_set_si (v_op, -1);
211 value_set_si (v_c, c);
213 ppl_new_Coefficient (&coef);
214 ppl_new_Linear_Expression_with_dimension (&expr, dim);
216 ppl_assign_Coefficient_from_mpz_t (coef, v);
217 ppl_Linear_Expression_add_to_coefficient (expr, pos1, coef);
218 ppl_assign_Coefficient_from_mpz_t (coef, v_op);
219 ppl_Linear_Expression_add_to_coefficient (expr, pos2, coef);
220 ppl_assign_Coefficient_from_mpz_t (coef, v_c);
221 ppl_Linear_Expression_add_to_inhomogeneous (expr, coef);
223 ppl_new_Constraint (&cstr, expr, cstr_type);
225 ppl_delete_Linear_Expression (expr);
226 ppl_delete_Coefficient (coef);
227 value_clear (v);
228 value_clear (v_op);
229 value_clear (v_c);
231 return cstr;
234 /* Builds subscript equality constraints. */
236 static ppl_Pointset_Powerset_C_Polyhedron_t
237 dr_equality_constraints (graphite_dim_t dim,
238 graphite_dim_t pos, graphite_dim_t nb_subscripts)
240 ppl_Polyhedron_t subscript_equalities;
241 ppl_Pointset_Powerset_C_Polyhedron_t res;
242 Value v, v_op;
243 graphite_dim_t i;
245 value_init (v);
246 value_init (v_op);
247 value_set_si (v, 1);
248 value_set_si (v_op, -1);
250 ppl_new_C_Polyhedron_from_space_dimension (&subscript_equalities, dim, 0);
251 for (i = 0; i < nb_subscripts; i++)
253 ppl_Linear_Expression_t expr;
254 ppl_Constraint_t cstr;
255 ppl_Coefficient_t coef;
257 ppl_new_Coefficient (&coef);
258 ppl_new_Linear_Expression_with_dimension (&expr, dim);
260 ppl_assign_Coefficient_from_mpz_t (coef, v);
261 ppl_Linear_Expression_add_to_coefficient (expr, pos + i, coef);
262 ppl_assign_Coefficient_from_mpz_t (coef, v_op);
263 ppl_Linear_Expression_add_to_coefficient (expr, pos + i + nb_subscripts,
264 coef);
266 ppl_new_Constraint (&cstr, expr, PPL_CONSTRAINT_TYPE_EQUAL);
267 ppl_Polyhedron_add_constraint (subscript_equalities, cstr);
269 ppl_delete_Linear_Expression (expr);
270 ppl_delete_Constraint (cstr);
271 ppl_delete_Coefficient (coef);
274 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron
275 (&res, subscript_equalities);
276 value_clear (v);
277 value_clear (v_op);
278 ppl_delete_Polyhedron (subscript_equalities);
280 return res;
283 /* Builds scheduling equality constraints. */
285 static ppl_Pointset_Powerset_C_Polyhedron_t
286 build_pairwise_scheduling_equality (graphite_dim_t dim,
287 graphite_dim_t pos, graphite_dim_t offset)
289 ppl_Pointset_Powerset_C_Polyhedron_t res;
290 ppl_Polyhedron_t equalities;
291 ppl_Constraint_t cstr;
293 ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
295 cstr = build_pairwise_constraint (dim, pos, pos + offset, 0,
296 PPL_CONSTRAINT_TYPE_EQUAL);
297 ppl_Polyhedron_add_constraint (equalities, cstr);
298 ppl_delete_Constraint (cstr);
300 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
301 ppl_delete_Polyhedron (equalities);
302 return res;
305 /* Builds scheduling inequality constraints. */
307 static ppl_Pointset_Powerset_C_Polyhedron_t
308 build_pairwise_scheduling_inequality (graphite_dim_t dim,
309 graphite_dim_t pos,
310 graphite_dim_t offset,
311 bool direction)
313 ppl_Pointset_Powerset_C_Polyhedron_t res;
314 ppl_Polyhedron_t equalities;
315 ppl_Constraint_t cstr;
317 ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
319 if (direction)
320 cstr = build_pairwise_constraint (dim, pos, pos + offset, -1,
321 PPL_CONSTRAINT_TYPE_GREATER_OR_EQUAL);
322 else
323 cstr = build_pairwise_constraint (dim, pos, pos + offset, 1,
324 PPL_CONSTRAINT_TYPE_LESS_OR_EQUAL);
326 ppl_Polyhedron_add_constraint (equalities, cstr);
327 ppl_delete_Constraint (cstr);
329 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
330 ppl_delete_Polyhedron (equalities);
331 return res;
334 /* Returns true when adding the lexicographical constraints at level I
335 to the RES dependence polyhedron returns an empty polyhedron. */
337 static bool
338 lexicographically_gt_p (ppl_Pointset_Powerset_C_Polyhedron_t res,
339 graphite_dim_t dim,
340 graphite_dim_t offset,
341 bool direction, graphite_dim_t i)
343 ppl_Pointset_Powerset_C_Polyhedron_t ineq;
344 bool empty_p;
346 ineq = build_pairwise_scheduling_inequality (dim, i, offset,
347 direction);
348 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (ineq, res);
349 empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (ineq);
350 if (!empty_p)
351 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, ineq);
352 ppl_delete_Pointset_Powerset_C_Polyhedron (ineq);
354 return !empty_p;
357 /* Build the precedence constraints for the lexicographical comparison
358 of time vectors RES following the lexicographical order. */
360 static void
361 build_lexicographically_gt_constraint (ppl_Pointset_Powerset_C_Polyhedron_t *res,
362 graphite_dim_t dim,
363 graphite_dim_t tdim1,
364 graphite_dim_t offset,
365 bool direction)
367 graphite_dim_t i;
369 if (lexicographically_gt_p (*res, dim, offset, direction, 0))
370 return;
372 for (i = 0; i < tdim1 - 1; i++)
374 ppl_Pointset_Powerset_C_Polyhedron_t sceq;
376 sceq = build_pairwise_scheduling_equality (dim, i, offset);
377 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (*res, sceq);
378 ppl_delete_Pointset_Powerset_C_Polyhedron (sceq);
380 if (lexicographically_gt_p (*res, dim, offset, direction, i + 1))
381 return;
384 if (i == tdim1 - 1)
386 ppl_delete_Pointset_Powerset_C_Polyhedron (*res);
387 ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (res, dim, 1);
391 /* Build the dependence polyhedron for data references PDR1 and PDR2. */
393 static poly_ddr_p
394 dependence_polyhedron_1 (poly_bb_p pbb1, poly_bb_p pbb2,
395 ppl_Pointset_Powerset_C_Polyhedron_t d1,
396 ppl_Pointset_Powerset_C_Polyhedron_t d2,
397 poly_dr_p pdr1, poly_dr_p pdr2,
398 ppl_Polyhedron_t s1, ppl_Polyhedron_t s2,
399 bool direction,
400 bool original_scattering_p)
402 scop_p scop = PBB_SCOP (pbb1);
403 graphite_dim_t tdim1 = original_scattering_p ?
404 pbb_nb_scattering_orig (pbb1) : pbb_nb_scattering_transform (pbb1);
405 graphite_dim_t tdim2 = original_scattering_p ?
406 pbb_nb_scattering_orig (pbb2) : pbb_nb_scattering_transform (pbb2);
407 graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
408 graphite_dim_t ddim2 = pbb_dim_iter_domain (pbb2);
409 graphite_dim_t sdim1 = PDR_NB_SUBSCRIPTS (pdr1) + 1;
410 graphite_dim_t gdim = scop_nb_params (scop);
411 graphite_dim_t dim1 = pdr_dim (pdr1);
412 graphite_dim_t dim2 = pdr_dim (pdr2);
413 graphite_dim_t dim = tdim1 + tdim2 + dim1 + dim2;
414 ppl_Pointset_Powerset_C_Polyhedron_t res;
415 ppl_Pointset_Powerset_C_Polyhedron_t id1, id2, isc1, isc2, idr1, idr2;
416 ppl_Pointset_Powerset_C_Polyhedron_t sc1, sc2, dreq;
418 gcc_assert (PBB_SCOP (pbb1) == PBB_SCOP (pbb2));
419 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&sc1, s1);
420 ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&sc2, s2);
422 id1 = map_into_dep_poly (dim, gdim, d1, ddim1, tdim1);
423 id2 = map_into_dep_poly (dim, gdim, d2, ddim2, tdim1 + ddim1 + tdim2);
424 isc1 = map_into_dep_poly (dim, gdim, sc1, ddim1 + tdim1, 0);
425 isc2 = map_into_dep_poly (dim, gdim, sc2, ddim2 + tdim2, tdim1 + ddim1);
427 idr1 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr1), ddim1, ddim1 + gdim,
428 tdim1, tdim2 + ddim2);
429 idr2 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr2), ddim2, ddim2 + gdim,
430 tdim1 + ddim1 + tdim2, sdim1);
432 /* Now add the subscript equalities. */
433 dreq = dr_equality_constraints (dim, tdim1 + ddim1 + tdim2 + ddim2, sdim1);
435 ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&res, dim, 0);
436 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, id1);
437 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, id2);
438 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, isc1);
439 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, isc2);
440 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr1);
441 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr2);
442 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, dreq);
443 ppl_delete_Pointset_Powerset_C_Polyhedron (id1);
444 ppl_delete_Pointset_Powerset_C_Polyhedron (id2);
445 ppl_delete_Pointset_Powerset_C_Polyhedron (sc1);
446 ppl_delete_Pointset_Powerset_C_Polyhedron (sc2);
447 ppl_delete_Pointset_Powerset_C_Polyhedron (isc1);
448 ppl_delete_Pointset_Powerset_C_Polyhedron (isc2);
449 ppl_delete_Pointset_Powerset_C_Polyhedron (idr1);
450 ppl_delete_Pointset_Powerset_C_Polyhedron (idr2);
451 ppl_delete_Pointset_Powerset_C_Polyhedron (dreq);
453 if (!ppl_Pointset_Powerset_C_Polyhedron_is_empty (res))
454 build_lexicographically_gt_constraint (&res, dim, MIN (tdim1, tdim2),
455 tdim1 + ddim1, direction);
457 return new_poly_ddr (pdr1, pdr2, res);
460 /* Build the dependence polyhedron for data references PDR1 and PDR2.
461 If possible use already cached information. */
463 static poly_ddr_p
464 dependence_polyhedron (poly_bb_p pbb1, poly_bb_p pbb2,
465 ppl_Pointset_Powerset_C_Polyhedron_t d1,
466 ppl_Pointset_Powerset_C_Polyhedron_t d2,
467 poly_dr_p pdr1, poly_dr_p pdr2,
468 ppl_Polyhedron_t s1, ppl_Polyhedron_t s2,
469 bool direction,
470 bool original_scattering_p)
472 PTR *x = NULL;
473 poly_ddr_p res;
475 if (original_scattering_p)
477 struct poly_ddr tmp;
479 tmp.source = pdr1;
480 tmp.sink = pdr2;
481 x = htab_find_slot (SCOP_ORIGINAL_PDDRS (PBB_SCOP (pbb1)),
482 &tmp, INSERT);
484 if (x && *x)
485 return (poly_ddr_p) *x;
488 res = dependence_polyhedron_1 (pbb1, pbb2, d1, d2, pdr1, pdr2,
489 s1, s2, direction, original_scattering_p);
491 if (original_scattering_p)
492 *x = res;
494 return res;
497 /* Returns the PDDR corresponding to the original schedule, or NULL if
498 the dependence relation is empty. */
500 static poly_ddr_p
501 pddr_original_scattering (poly_bb_p pbb1, poly_bb_p pbb2,
502 poly_dr_p pdr1, poly_dr_p pdr2)
504 poly_ddr_p pddr;
505 ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
506 ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
507 ppl_Polyhedron_t so1 = PBB_ORIGINAL_SCATTERING (pbb1);
508 ppl_Polyhedron_t so2 = PBB_ORIGINAL_SCATTERING (pbb2);
510 if (PDR_NB_SUBSCRIPTS (pdr1) != PDR_NB_SUBSCRIPTS (pdr2)
511 || (pdr_read_p (pdr1) && pdr_read_p (pdr2)))
512 return NULL;
514 pddr = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, so1, so2,
515 true, true);
516 if (pddr_is_empty (pddr))
517 return NULL;
519 return pddr;
522 /* Returns true when the PBB_TRANSFORMED_SCATTERING functions of PBB1
523 and PBB2 respect the data dependences of PBB_ORIGINAL_SCATTERING
524 functions. */
526 static bool
527 graphite_legal_transform_dr (poly_bb_p pbb1, poly_bb_p pbb2,
528 poly_dr_p pdr1, poly_dr_p pdr2)
530 ppl_Polyhedron_t st1, st2;
531 ppl_Pointset_Powerset_C_Polyhedron_t po, pt;
532 graphite_dim_t ddim1, otdim1, otdim2, ttdim1, ttdim2;
533 ppl_Pointset_Powerset_C_Polyhedron_t temp;
534 ppl_dimension_type pdim;
535 bool is_empty_p;
536 poly_ddr_p pddr;
537 ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
538 ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
540 pddr = pddr_original_scattering (pbb1, pbb2, pdr1, pdr2);
541 if (!pddr)
542 return true;
544 po = PDDR_DDP (pddr);
546 if (dump_file && (dump_flags & TDF_DETAILS))
547 fprintf (dump_file, "\nloop carries dependency.\n");
549 st1 = PBB_TRANSFORMED_SCATTERING (pbb1);
550 st2 = PBB_TRANSFORMED_SCATTERING (pbb2);
551 ddim1 = pbb_dim_iter_domain (pbb1);
552 otdim1 = pbb_nb_scattering_orig (pbb1);
553 otdim2 = pbb_nb_scattering_orig (pbb2);
554 ttdim1 = pbb_nb_scattering_transform (pbb1);
555 ttdim2 = pbb_nb_scattering_transform (pbb2);
557 /* Copy the PO polyhedron into the TEMP, so it is not destroyed.
558 Keep in mind, that PO polyhedron might be restored from the cache
559 and should not be modified! */
560 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &pdim);
561 ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&temp, pdim, 0);
562 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (temp, po);
564 pddr = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, st1, st2,
565 false, false);
566 pt = PDDR_DDP (pddr);
568 /* Extend PO and PT to have the same dimensions. */
569 ppl_insert_dimensions_pointset (temp, otdim1, ttdim1);
570 ppl_insert_dimensions_pointset (temp, otdim1 + ttdim1 + ddim1 + otdim2, ttdim2);
571 ppl_insert_dimensions_pointset (pt, 0, otdim1);
572 ppl_insert_dimensions_pointset (pt, otdim1 + ttdim1 + ddim1, otdim2);
574 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (temp, pt);
575 is_empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (temp);
577 ppl_delete_Pointset_Powerset_C_Polyhedron (temp);
578 free_poly_ddr (pddr);
580 return is_empty_p;
583 /* Iterates over the data references of PBB1 and PBB2 and detect
584 whether the transformed schedule is correct. */
586 static bool
587 graphite_legal_transform_bb (poly_bb_p pbb1, poly_bb_p pbb2)
589 int i, j;
590 poly_dr_p pdr1, pdr2;
592 if (!PBB_PDR_DUPLICATES_REMOVED (pbb1))
593 pbb_remove_duplicate_pdrs (pbb1);
595 if (!PBB_PDR_DUPLICATES_REMOVED (pbb2))
596 pbb_remove_duplicate_pdrs (pbb2);
598 for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr1); i++)
599 for (j = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), j, pdr2); j++)
600 if (!graphite_legal_transform_dr (pbb1, pbb2, pdr1, pdr2))
601 return false;
603 return true;
606 /* Iterates over the SCOP and detect whether the transformed schedule
607 is correct. */
609 bool
610 graphite_legal_transform (scop_p scop)
612 int i, j;
613 poly_bb_p pbb1, pbb2;
615 timevar_push (TV_GRAPHITE_DATA_DEPS);
617 for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
618 for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
619 if (!graphite_legal_transform_bb (pbb1, pbb2))
621 timevar_pop (TV_GRAPHITE_DATA_DEPS);
622 return false;
625 timevar_pop (TV_GRAPHITE_DATA_DEPS);
626 return true;
629 /* Remove all the dimensions except alias information at dimension
630 ALIAS_DIM. */
632 static void
633 build_alias_set_powerset (ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset,
634 ppl_dimension_type alias_dim)
636 ppl_dimension_type *ds;
637 ppl_dimension_type access_dim;
638 unsigned i, pos = 0;
640 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (alias_powerset,
641 &access_dim);
642 ds = XNEWVEC (ppl_dimension_type, access_dim-1);
643 for (i = 0; i < access_dim; i++)
645 if (i == alias_dim)
646 continue;
648 ds[pos] = i;
649 pos++;
652 ppl_Pointset_Powerset_C_Polyhedron_remove_space_dimensions (alias_powerset,
654 access_dim - 1);
655 free (ds);
658 /* Return true when PDR1 and PDR2 may alias. */
660 static bool
661 poly_drs_may_alias_p (poly_dr_p pdr1, poly_dr_p pdr2)
663 ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset1, alias_powerset2;
664 ppl_Pointset_Powerset_C_Polyhedron_t accesses1 = PDR_ACCESSES (pdr1);
665 ppl_Pointset_Powerset_C_Polyhedron_t accesses2 = PDR_ACCESSES (pdr2);
666 ppl_dimension_type alias_dim1 = pdr_alias_set_dim (pdr1);
667 ppl_dimension_type alias_dim2 = pdr_alias_set_dim (pdr2);
668 int empty_p;
670 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
671 (&alias_powerset1, accesses1);
672 ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
673 (&alias_powerset2, accesses2);
675 build_alias_set_powerset (alias_powerset1, alias_dim1);
676 build_alias_set_powerset (alias_powerset2, alias_dim2);
678 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign
679 (alias_powerset1, alias_powerset2);
681 empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (alias_powerset1);
683 ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset1);
684 ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset2);
686 return !empty_p;
689 /* Returns TRUE when the dependence polyhedron between PDR1 and
690 PDR2 represents a loop carried dependence at level LEVEL. */
692 static bool
693 graphite_carried_dependence_level_k (poly_dr_p pdr1, poly_dr_p pdr2,
694 int level)
696 poly_bb_p pbb1 = PDR_PBB (pdr1);
697 poly_bb_p pbb2 = PDR_PBB (pdr2);
698 ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
699 ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
700 ppl_Polyhedron_t so1 = PBB_TRANSFORMED_SCATTERING (pbb1);
701 ppl_Polyhedron_t so2 = PBB_TRANSFORMED_SCATTERING (pbb2);
702 ppl_Pointset_Powerset_C_Polyhedron_t po;
703 ppl_Pointset_Powerset_C_Polyhedron_t eqpp;
704 graphite_dim_t tdim1 = pbb_nb_scattering_transform (pbb1);
705 graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
706 ppl_dimension_type dim;
707 bool empty_p;
708 poly_ddr_p pddr;
710 if ((PDR_TYPE (pdr1) == PDR_READ && PDR_TYPE (pdr2) == PDR_READ)
711 || !poly_drs_may_alias_p (pdr1, pdr2))
712 return false;
714 if (PDR_NB_SUBSCRIPTS (pdr1) != PDR_NB_SUBSCRIPTS (pdr2))
715 return true;
717 pddr = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, so1, so2,
718 true, false);
720 if (pddr_is_empty (pddr))
721 return false;
723 po = PDDR_DDP (pddr);
724 ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &dim);
725 eqpp = build_pairwise_scheduling_inequality (dim, level, tdim1 + ddim1, 1);
727 ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (eqpp, po);
728 empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (eqpp);
730 ppl_delete_Pointset_Powerset_C_Polyhedron (eqpp);
731 return !empty_p;
734 /* Check data dependency between PBB1 and PBB2 at level LEVEL. */
736 bool
737 dependency_between_pbbs_p (poly_bb_p pbb1, poly_bb_p pbb2, int level)
739 int i, j;
740 poly_dr_p pdr1, pdr2;
742 timevar_push (TV_GRAPHITE_DATA_DEPS);
744 for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr1); i++)
745 for (j = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), j, pdr2); j++)
746 if (graphite_carried_dependence_level_k (pdr1, pdr2, level))
748 timevar_pop (TV_GRAPHITE_DATA_DEPS);
749 return true;
752 timevar_pop (TV_GRAPHITE_DATA_DEPS);
753 return false;
756 /* Pretty print to FILE all the data dependences of SCoP in DOT
757 format. */
759 static void
760 dot_deps_1 (FILE *file, scop_p scop)
762 int i, j, k, l;
763 poly_bb_p pbb1, pbb2;
764 poly_dr_p pdr1, pdr2;
766 fputs ("digraph all {\n", file);
768 for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
769 for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
770 for (k = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), k, pdr1); k++)
771 for (l = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), l, pdr2); l++)
772 if (pddr_original_scattering (pbb1, pbb2, pdr1, pdr2))
773 fprintf (file, "S%d_D%d -> S%d_D%d\n",
774 pbb_index (pbb1), PDR_ID (pdr1),
775 pbb_index (pbb2), PDR_ID (pdr2));
777 fputs ("}\n\n", file);
780 /* Display all the data dependences in SCoP using dotty. */
782 void
783 dot_deps (scop_p scop)
785 /* When debugging, enable the following code. This cannot be used
786 in production compilers because it calls "system". */
787 #if 0
788 int x;
789 FILE *stream = fopen ("/tmp/scopdeps.dot", "w");
790 gcc_assert (stream);
792 dot_deps_1 (stream, scop);
793 fclose (stream);
795 x = system ("dotty /tmp/scopdeps.dot");
796 #else
797 dot_deps_1 (stderr, scop);
798 #endif
802 #endif