OSDN Git Service

59e2a0d4da23b6c589357f642c4004e2716c87a6
[pf3gnuchains/gcc-fork.git] / gcc / graphite-dependences.c
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>.
5
6 This file is part of GCC.
7
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.
12
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.
17
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/>.  */
21
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"
43
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"
52
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).  */
58
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)
63 {
64   poly_dr_pair_p pdrpp;
65
66   pdrpp = XNEW (struct poly_dr_pair);
67   pdrpp->source = source;
68   pdrpp->sink = sink;
69   pdrpp->ddp = ddp;
70
71   return pdrpp;
72 }
73
74 /* Comparison function for poly_dr_pair hash table.  */
75
76 int
77 eq_poly_dr_pair_p (const void *pdrpp1, const void *pdrpp2)
78 {
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;
81
82   return (p1->source == p2->source
83           && p1->sink == p2->sink);
84 }
85
86 /* Hash function for poly_dr_pair hashtable.  */
87
88 hashval_t
89 hash_poly_dr_pair_p (const void *pdrpp)
90 {
91   const struct poly_dr_pair *p = (const struct poly_dr_pair *) pdrpp;
92
93   return (hashval_t) ((long) p->source + (long) p->sink);
94 }
95
96 /* Returns a polyhedron of dimension DIM.
97
98    Maps the dimensions [0, ..., cut - 1] of polyhedron P to OFFSET0
99    and the dimensions [cut, ..., nb_dim] to DIM - GDIM.  */
100
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)
106 {
107   ppl_Pointset_Powerset_C_Polyhedron_t res;
108
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);
114
115   return res;
116 }
117
118 /* Swap [cut0, ..., cut1] to the end of DR: "a CUT0 b CUT1 c" is
119    transformed into "a CUT0 c CUT1' b"
120
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".  */
125
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)
131 {
132   ppl_dimension_type pdim;
133   ppl_dimension_type *map;
134   ppl_Pointset_Powerset_C_Polyhedron_t res;
135   ppl_dimension_type i;
136
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);
140
141   map = (ppl_dimension_type *) XNEWVEC (ppl_dimension_type, pdim);
142
143   /* First mapping: move 'g' vector to right position.  */
144   for (i = 0; i < cut0; i++)
145     map[i] = i;
146
147   for (i = cut0; i < cut1; i++)
148     map[i] = pdim - cut1 + i;
149
150   for (i = cut1; i < pdim; i++)
151     map[i] = cut0 + i - cut1;
152
153   ppl_Pointset_Powerset_C_Polyhedron_map_space_dimensions (res, map, pdim);
154   free (map);
155
156   /* After swapping 's' and 'g' vectors, we have to update a new cut.  */
157   cut1 = pdim - cut1 + cut0;
158
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);
163
164   return res;
165 }
166
167 /* Builds a constraints of the form "POS1 - POS2 CSTR_TYPE C" */
168
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)
173 {
174   ppl_Linear_Expression_t expr;
175   ppl_Constraint_t cstr;
176   ppl_Coefficient_t coef;
177   Value v, v_op, v_c;
178
179   value_init (v);
180   value_init (v_op);
181   value_init (v_c);
182
183   value_set_si (v, 1);
184   value_set_si (v_op, -1);
185   value_set_si (v_c, c);
186
187   ppl_new_Coefficient (&coef);
188   ppl_new_Linear_Expression_with_dimension (&expr, dim);
189
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);
196
197   ppl_new_Constraint (&cstr, expr, cstr_type);
198
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);
204
205   return cstr;
206 }
207
208 /* Builds subscript equality constraints.  */
209
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)
213 {
214   ppl_Polyhedron_t subscript_equalities;
215   ppl_Pointset_Powerset_C_Polyhedron_t res;
216   Value v, v_op;
217   graphite_dim_t i;
218
219   value_init (v);
220   value_init (v_op);
221   value_set_si (v, 1);
222   value_set_si (v_op, -1);
223
224   ppl_new_C_Polyhedron_from_space_dimension (&subscript_equalities, dim, 0);
225   for (i = 0; i < nb_subscripts; i++)
226     {
227       ppl_Linear_Expression_t expr;
228       ppl_Constraint_t cstr;
229       ppl_Coefficient_t coef;
230
231       ppl_new_Coefficient (&coef);
232       ppl_new_Linear_Expression_with_dimension (&expr, dim);
233
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);
239
240       ppl_new_Constraint (&cstr, expr, PPL_CONSTRAINT_TYPE_EQUAL);
241       ppl_Polyhedron_add_constraint (subscript_equalities, cstr);
242
243       ppl_delete_Linear_Expression (expr);
244       ppl_delete_Constraint (cstr);
245       ppl_delete_Coefficient (coef);
246     }
247
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);
253
254   return res;
255 }
256
257 /* Builds scheduling equality constraints.  */
258
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)
262 {
263   ppl_Pointset_Powerset_C_Polyhedron_t res;
264   ppl_Polyhedron_t equalities;
265   ppl_Constraint_t cstr;
266
267   ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
268
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);
273
274   ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
275   ppl_delete_Polyhedron (equalities);
276   return res;
277 }
278
279 /* Builds scheduling inequality constraints.  */
280
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)
286 {
287   ppl_Pointset_Powerset_C_Polyhedron_t res;
288   ppl_Polyhedron_t equalities;
289   ppl_Constraint_t cstr;
290
291   ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
292
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);
299
300   ppl_Polyhedron_add_constraint (equalities, cstr);
301   ppl_delete_Constraint (cstr);
302
303   ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
304   ppl_delete_Polyhedron (equalities);
305   return res;
306 }
307
308 /* Returns true when adding the lexicographical constraints at level I
309    to the RES dependence polyhedron returns an empty polyhedron.  */
310
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)
316 {
317   ppl_Pointset_Powerset_C_Polyhedron_t ineq;
318   bool empty_p;
319
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);
327
328   return !empty_p;
329 }
330
331 /* Build the precedence constraints for the lexicographical comparison
332    of time vectors RES following the lexicographical order.  */
333
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)
340 {
341   graphite_dim_t i;
342
343   if (lexicographically_gt_p (*res, dim, offset, direction, 0))
344     return;
345
346   for (i = 0; i < tdim1 - 1; i++)
347     {
348       ppl_Pointset_Powerset_C_Polyhedron_t sceq;
349
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);
353
354       if (lexicographically_gt_p (*res, dim, offset, direction, i + 1))
355         return;
356     }
357
358   if (i == tdim1 - 1)
359     {
360       ppl_delete_Pointset_Powerset_C_Polyhedron (*res);
361       ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (res, dim, 1);
362     }
363 }
364
365 /* Build the dependence polyhedron for data references PDR1 and PDR2.  */
366
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)
375 {
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;
391
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);
395
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);
400
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);
405
406   /* Now add the subscript equalities.  */
407   dreq = dr_equality_constraints (dim, tdim1 + ddim1 + tdim2 + ddim2, sdim1);
408
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);
426
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;
431 }
432
433 /* Build the dependence polyhedron for data references PDR1 and PDR2.
434    If possible use already cached information.  */
435
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)
444 {
445   poly_dr_pair tmp;
446   PTR *x = NULL;
447   ppl_Pointset_Powerset_C_Polyhedron_t res;
448
449   if (original_scattering_p)
450     {
451       tmp.source = pdr1;
452       tmp.sink = pdr2;
453       x = htab_find_slot (SCOP_ORIGINAL_PDR_PAIRS (PBB_SCOP (pbb1)),
454                           &tmp, INSERT);
455
456       if (x && *x)
457         {
458           if (dump_file && (dump_flags & TDF_DETAILS))
459             fprintf (dump_file, "\nddp cache: hit.\n");
460           return ((poly_dr_pair *)*x)->ddp;
461         }
462       else if (dump_file && (dump_flags & TDF_DETAILS))
463         fprintf (dump_file, "\nddp cache: miss.\n");
464     }
465
466   res = dependence_polyhedron_1 (pbb1, pbb2, d1, d2, pdr1, pdr2,
467                                  s1, s2, direction, original_scattering_p);
468
469   if (original_scattering_p)
470     {
471       gcc_assert (x && *x == NULL);
472       *x = new_poly_dr_pair (pdr1, pdr2, res);
473
474       if (dump_file && (dump_flags & TDF_DETAILS))
475         fprintf (dump_file, "\nddp cache: add element.\n");
476     }
477
478   return res;
479 }
480
481 /* Returns true when the PBB_TRANSFORMED_SCATTERING functions of PBB1
482    and PBB2 respect the data dependences of PBB_ORIGINAL_SCATTERING
483    functions.  */
484
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)
488 {
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;
494
495   graphite_dim_t sdim1 = PDR_NB_SUBSCRIPTS (pdr1) + 1;
496   graphite_dim_t sdim2 = PDR_NB_SUBSCRIPTS (pdr2) + 1;
497
498   if (sdim1 != sdim2)
499     return true;
500
501   po = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, so1, so2,
502                               true, true);
503
504   if (ppl_Pointset_Powerset_C_Polyhedron_is_empty (po))
505     return true;
506   else
507     {
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;
519
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);
527
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);
532
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);
539
540       ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (temp, pt);
541       is_empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (temp);
542
543       ppl_delete_Pointset_Powerset_C_Polyhedron (temp);
544       ppl_delete_Pointset_Powerset_C_Polyhedron (pt);
545       return is_empty_p;
546     }
547 }
548
549 /* Iterates over the data references of PBB1 and PBB2 and detect
550    whether the transformed schedule is correct.  */
551
552 static bool
553 graphite_legal_transform_bb (poly_bb_p pbb1, poly_bb_p pbb2)
554 {
555   int i, j;
556   poly_dr_p pdr1, pdr2;
557
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;
563 }
564
565 /* Iterates over the SCOP and detect whether the transformed schedule
566    is correct.  */
567
568 bool
569 graphite_legal_transform (scop_p scop)
570 {
571   int i, j;
572   poly_bb_p pbb1, pbb2;
573
574   timevar_push (TV_GRAPHITE_DATA_DEPS);
575
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))
579         {
580           timevar_pop (TV_GRAPHITE_DATA_DEPS);
581           return false;
582         }
583
584   timevar_pop (TV_GRAPHITE_DATA_DEPS);
585   return true;
586 }
587
588 /* Remove all the dimensions except alias information at dimension
589    ALIAS_DIM.  */
590
591 static void
592 build_alias_set_powerset (ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset,
593                           ppl_dimension_type alias_dim)
594 {
595   ppl_dimension_type *ds;
596   ppl_dimension_type access_dim;
597   unsigned i, pos = 0;
598
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++)
603     {
604       if (i == alias_dim)
605         continue;
606
607       ds[pos] = i;
608       pos++;
609     }
610
611   ppl_Pointset_Powerset_C_Polyhedron_remove_space_dimensions (alias_powerset,
612                                                               ds,
613                                                               access_dim - 1);
614   free (ds);
615 }
616
617 /* Return true when PDR1 and PDR2 may alias.  */
618
619 static bool
620 poly_drs_may_alias_p (poly_dr_p pdr1, poly_dr_p pdr2)
621 {
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;
628
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);
633
634   build_alias_set_powerset (alias_powerset1, alias_dim1);
635   build_alias_set_powerset (alias_powerset2, alias_dim2);
636
637   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign
638     (alias_powerset1, alias_powerset2);
639
640   empty_p =  ppl_Pointset_Powerset_C_Polyhedron_is_empty (alias_powerset1);
641
642   ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset1);
643   ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset2);
644
645   return !empty_p;
646 }
647
648 /* Returns TRUE when the dependence polyhedron between PDR1 and
649    PDR2 represents a loop carried dependence at level LEVEL. Otherwise
650    return FALSE.  */
651
652 static bool
653 graphite_carried_dependence_level_k (poly_dr_p pdr1, poly_dr_p pdr2,
654                                      int level)
655 {
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;
670
671   if ((PDR_TYPE (pdr1) == PDR_READ && PDR_TYPE (pdr2) == PDR_READ)
672       || !poly_drs_may_alias_p (pdr1, pdr2))
673     return false;
674
675   if (sdim1 != sdim2)
676     return true;
677
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))
681     {
682       ppl_delete_Pointset_Powerset_C_Polyhedron (po);
683       return false;
684     }
685
686   ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &dim);
687   eqpp = build_pairwise_scheduling_inequality (dim, level, tdim1 + ddim1, 1);
688
689   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (eqpp, po);
690   empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (eqpp);
691
692   ppl_delete_Pointset_Powerset_C_Polyhedron (eqpp);
693   return !empty_p;
694 }
695
696 /* Check data dependency between PBB1 and PBB2 at level LEVEL.  */
697
698 bool
699 dependency_between_pbbs_p (poly_bb_p pbb1, poly_bb_p pbb2, int level)
700 {
701   int i, j;
702   poly_dr_p pdr1, pdr2;
703
704   timevar_push (TV_GRAPHITE_DATA_DEPS);
705
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))
709         {
710           timevar_pop (TV_GRAPHITE_DATA_DEPS);
711           return true;
712         }
713
714   timevar_pop (TV_GRAPHITE_DATA_DEPS);
715   return false;
716 }
717
718 #endif