OSDN Git Service

2009-10-17 Sebastian Pop <sebastian.pop@amd.com>
[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 /* 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).  */
56
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)
60 {
61   poly_ddr_p pddr;
62
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;
68
69   return pddr;
70 }
71
72 /* Free the poly_ddr_p P.  */
73
74 void
75 free_poly_ddr (void *p)
76 {
77   poly_ddr_p pddr = (poly_ddr_p) p;
78   ppl_delete_Pointset_Powerset_C_Polyhedron (PDDR_DDP (pddr));
79   free (pddr);
80 }
81
82 /* Comparison function for poly_ddr hash table.  */
83
84 int
85 eq_poly_ddr_p (const void *pddr1, const void *pddr2)
86 {
87   const struct poly_ddr *p1 = (const struct poly_ddr *) pddr1;
88   const struct poly_ddr *p2 = (const struct poly_ddr *) pddr2;
89
90   return (PDDR_SOURCE (p1) == PDDR_SOURCE (p2)
91           && PDDR_SINK (p1) == PDDR_SINK (p2));
92 }
93
94 /* Hash function for poly_ddr hashtable.  */
95
96 hashval_t
97 hash_poly_ddr_p (const void *pddr)
98 {
99   const struct poly_ddr *p = (const struct poly_ddr *) pddr;
100
101   return (hashval_t) ((long) PDDR_SOURCE (p) + (long) PDDR_SINK (p));
102 }
103
104 /* Returns true when PDDR has no dependence.  */
105
106 static bool
107 pddr_is_empty (poly_ddr_p pddr)
108 {
109   if (PDDR_KIND (pddr) != unknown_dependence)
110     return PDDR_KIND (pddr) == no_dependence ? true : false;
111
112   if (ppl_Pointset_Powerset_C_Polyhedron_is_empty (PDDR_DDP (pddr)))
113     {
114       PDDR_KIND (pddr) = no_dependence;
115       return true;
116     }
117
118   PDDR_KIND (pddr) = has_dependence;
119   return false;
120 }
121
122 /* Returns a polyhedron of dimension DIM.
123
124    Maps the dimensions [0, ..., cut - 1] of polyhedron P to OFFSET
125    and the dimensions [cut, ..., nb_dim] to DIM - GDIM.  */
126
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)
132 {
133   ppl_Pointset_Powerset_C_Polyhedron_t res;
134
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);
140
141   return res;
142 }
143
144 /* Swap [cut0, ..., cut1] to the end of DR: "a CUT0 b CUT1 c" is
145    transformed into "a CUT0 c CUT1' b"
146
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".  */
151
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)
157 {
158   ppl_dimension_type pdim;
159   ppl_dimension_type *map;
160   ppl_Pointset_Powerset_C_Polyhedron_t res;
161   ppl_dimension_type i;
162
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);
166
167   map = (ppl_dimension_type *) XNEWVEC (ppl_dimension_type, pdim);
168
169   /* First mapping: move 'g' vector to right position.  */
170   for (i = 0; i < cut0; i++)
171     map[i] = i;
172
173   for (i = cut0; i < cut1; i++)
174     map[i] = pdim - cut1 + i;
175
176   for (i = cut1; i < pdim; i++)
177     map[i] = cut0 + i - cut1;
178
179   ppl_Pointset_Powerset_C_Polyhedron_map_space_dimensions (res, map, pdim);
180   free (map);
181
182   /* After swapping 's' and 'g' vectors, we have to update a new cut.  */
183   cut1 = pdim - cut1 + cut0;
184
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);
189
190   return res;
191 }
192
193 /* Builds a constraints of the form "POS1 - POS2 CSTR_TYPE C" */
194
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)
199 {
200   ppl_Linear_Expression_t expr;
201   ppl_Constraint_t cstr;
202   ppl_Coefficient_t coef;
203   Value v, v_op, v_c;
204
205   value_init (v);
206   value_init (v_op);
207   value_init (v_c);
208
209   value_set_si (v, 1);
210   value_set_si (v_op, -1);
211   value_set_si (v_c, c);
212
213   ppl_new_Coefficient (&coef);
214   ppl_new_Linear_Expression_with_dimension (&expr, dim);
215
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);
222
223   ppl_new_Constraint (&cstr, expr, cstr_type);
224
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);
230
231   return cstr;
232 }
233
234 /* Builds subscript equality constraints.  */
235
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)
239 {
240   ppl_Polyhedron_t subscript_equalities;
241   ppl_Pointset_Powerset_C_Polyhedron_t res;
242   Value v, v_op;
243   graphite_dim_t i;
244
245   value_init (v);
246   value_init (v_op);
247   value_set_si (v, 1);
248   value_set_si (v_op, -1);
249
250   ppl_new_C_Polyhedron_from_space_dimension (&subscript_equalities, dim, 0);
251   for (i = 0; i < nb_subscripts; i++)
252     {
253       ppl_Linear_Expression_t expr;
254       ppl_Constraint_t cstr;
255       ppl_Coefficient_t coef;
256
257       ppl_new_Coefficient (&coef);
258       ppl_new_Linear_Expression_with_dimension (&expr, dim);
259
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);
265
266       ppl_new_Constraint (&cstr, expr, PPL_CONSTRAINT_TYPE_EQUAL);
267       ppl_Polyhedron_add_constraint (subscript_equalities, cstr);
268
269       ppl_delete_Linear_Expression (expr);
270       ppl_delete_Constraint (cstr);
271       ppl_delete_Coefficient (coef);
272     }
273
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);
279
280   return res;
281 }
282
283 /* Builds scheduling equality constraints.  */
284
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)
288 {
289   ppl_Pointset_Powerset_C_Polyhedron_t res;
290   ppl_Polyhedron_t equalities;
291   ppl_Constraint_t cstr;
292
293   ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
294
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);
299
300   ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
301   ppl_delete_Polyhedron (equalities);
302   return res;
303 }
304
305 /* Builds scheduling inequality constraints.  */
306
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)
312 {
313   ppl_Pointset_Powerset_C_Polyhedron_t res;
314   ppl_Polyhedron_t equalities;
315   ppl_Constraint_t cstr;
316
317   ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
318
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);
325
326   ppl_Polyhedron_add_constraint (equalities, cstr);
327   ppl_delete_Constraint (cstr);
328
329   ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
330   ppl_delete_Polyhedron (equalities);
331   return res;
332 }
333
334 /* Returns true when adding the lexicographical constraints at level I
335    to the RES dependence polyhedron returns an empty polyhedron.  */
336
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)
342 {
343   ppl_Pointset_Powerset_C_Polyhedron_t ineq;
344   bool empty_p;
345
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);
353
354   return !empty_p;
355 }
356
357 /* Build the precedence constraints for the lexicographical comparison
358    of time vectors RES following the lexicographical order.  */
359
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)
366 {
367   graphite_dim_t i;
368
369   if (lexicographically_gt_p (*res, dim, offset, direction, 0))
370     return;
371
372   for (i = 0; i < tdim1 - 1; i++)
373     {
374       ppl_Pointset_Powerset_C_Polyhedron_t sceq;
375
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);
379
380       if (lexicographically_gt_p (*res, dim, offset, direction, i + 1))
381         return;
382     }
383
384   if (i == tdim1 - 1)
385     {
386       ppl_delete_Pointset_Powerset_C_Polyhedron (*res);
387       ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (res, dim, 1);
388     }
389 }
390
391 /* Build the dependence polyhedron for data references PDR1 and PDR2.
392    The layout of the dependence polyhedron is:
393
394    T1|I1|T2|I2|S1|S2|G
395
396    with
397    | T1 and T2 the scattering dimensions for PDR1 and PDR2
398    | I1 and I2 the iteration domains
399    | S1 and S2 the subscripts
400    | G the global parameters.  */
401
402 static poly_ddr_p
403 dependence_polyhedron_1 (poly_bb_p pbb1, poly_bb_p pbb2,
404                          ppl_Pointset_Powerset_C_Polyhedron_t d1,
405                          ppl_Pointset_Powerset_C_Polyhedron_t d2,
406                          poly_dr_p pdr1, poly_dr_p pdr2,
407                          ppl_Polyhedron_t s1, ppl_Polyhedron_t s2,
408                          bool direction,
409                          bool original_scattering_p)
410 {
411   scop_p scop = PBB_SCOP (pbb1);
412   graphite_dim_t tdim1 = original_scattering_p ?
413     pbb_nb_scattering_orig (pbb1) : pbb_nb_scattering_transform (pbb1);
414   graphite_dim_t tdim2 = original_scattering_p ?
415     pbb_nb_scattering_orig (pbb2) : pbb_nb_scattering_transform (pbb2);
416   graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
417   graphite_dim_t ddim2 = pbb_dim_iter_domain (pbb2);
418   graphite_dim_t sdim1 = PDR_NB_SUBSCRIPTS (pdr1) + 1;
419   graphite_dim_t gdim = scop_nb_params (scop);
420   graphite_dim_t dim1 = pdr_dim (pdr1);
421   graphite_dim_t dim2 = pdr_dim (pdr2);
422   graphite_dim_t dim = tdim1 + tdim2 + dim1 + dim2;
423   ppl_Pointset_Powerset_C_Polyhedron_t res;
424   ppl_Pointset_Powerset_C_Polyhedron_t id1, id2, isc1, isc2, idr1, idr2;
425   ppl_Pointset_Powerset_C_Polyhedron_t sc1, sc2, dreq;
426   ppl_Pointset_Powerset_C_Polyhedron_t context;
427
428   gcc_assert (PBB_SCOP (pbb1) == PBB_SCOP (pbb2));
429
430   ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
431     (&context, SCOP_CONTEXT (scop));
432   ppl_insert_dimensions_pointset (context, 0, dim - gdim);
433
434   ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&sc1, s1);
435   ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&sc2, s2);
436
437   id1 = map_into_dep_poly (dim, gdim, d1, ddim1, tdim1);
438   id2 = map_into_dep_poly (dim, gdim, d2, ddim2, tdim1 + ddim1 + tdim2);
439   isc1 = map_into_dep_poly (dim, gdim, sc1, ddim1 + tdim1, 0);
440   isc2 = map_into_dep_poly (dim, gdim, sc2, ddim2 + tdim2, tdim1 + ddim1);
441
442   idr1 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr1), ddim1, ddim1 + gdim,
443                                tdim1, tdim2 + ddim2);
444   idr2 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr2), ddim2, ddim2 + gdim,
445                                tdim1 + ddim1 + tdim2, sdim1);
446
447   /* Now add the subscript equalities.  */
448   dreq = dr_equality_constraints (dim, tdim1 + ddim1 + tdim2 + ddim2, sdim1);
449
450   ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&res, dim, 0);
451   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, context);
452   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, id1);
453   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, id2);
454   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, isc1);
455   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, isc2);
456   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr1);
457   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr2);
458   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, dreq);
459   ppl_delete_Pointset_Powerset_C_Polyhedron (context);
460   ppl_delete_Pointset_Powerset_C_Polyhedron (id1);
461   ppl_delete_Pointset_Powerset_C_Polyhedron (id2);
462   ppl_delete_Pointset_Powerset_C_Polyhedron (sc1);
463   ppl_delete_Pointset_Powerset_C_Polyhedron (sc2);
464   ppl_delete_Pointset_Powerset_C_Polyhedron (isc1);
465   ppl_delete_Pointset_Powerset_C_Polyhedron (isc2);
466   ppl_delete_Pointset_Powerset_C_Polyhedron (idr1);
467   ppl_delete_Pointset_Powerset_C_Polyhedron (idr2);
468   ppl_delete_Pointset_Powerset_C_Polyhedron (dreq);
469
470   if (!ppl_Pointset_Powerset_C_Polyhedron_is_empty (res))
471     build_lexicographically_gt_constraint (&res, dim, MIN (tdim1, tdim2),
472                                            tdim1 + ddim1, direction);
473
474   return new_poly_ddr (pdr1, pdr2, res);
475 }
476
477 /* Build the dependence polyhedron for data references PDR1 and PDR2.
478    If possible use already cached information.  */
479
480 static poly_ddr_p
481 dependence_polyhedron (poly_bb_p pbb1, poly_bb_p pbb2,
482                        ppl_Pointset_Powerset_C_Polyhedron_t d1,
483                        ppl_Pointset_Powerset_C_Polyhedron_t d2,
484                        poly_dr_p pdr1, poly_dr_p pdr2,
485                        ppl_Polyhedron_t s1, ppl_Polyhedron_t s2,
486                        bool direction,
487                        bool original_scattering_p)
488 {
489   PTR *x = NULL;
490   poly_ddr_p res;
491
492   if (original_scattering_p)
493     {
494       struct poly_ddr tmp;
495
496       tmp.source = pdr1;
497       tmp.sink = pdr2;
498       x = htab_find_slot (SCOP_ORIGINAL_PDDRS (PBB_SCOP (pbb1)),
499                           &tmp, INSERT);
500
501       if (x && *x)
502         return (poly_ddr_p) *x;
503     }
504
505   res = dependence_polyhedron_1 (pbb1, pbb2, d1, d2, pdr1, pdr2,
506                                  s1, s2, direction, original_scattering_p);
507
508   if (original_scattering_p)
509     *x = res;
510
511   return res;
512 }
513
514 static bool
515 poly_drs_may_alias_p (poly_dr_p pdr1, poly_dr_p pdr2);
516
517 /* Returns the PDDR corresponding to the original schedule, or NULL if
518    the dependence relation is empty or unknown (Can't judge dependency
519    under polyhedral model.  */
520
521 static poly_ddr_p
522 pddr_original_scattering (poly_bb_p pbb1, poly_bb_p pbb2,
523                           poly_dr_p pdr1, poly_dr_p pdr2)
524 {
525   poly_ddr_p pddr;
526   ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
527   ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
528   ppl_Polyhedron_t so1 = PBB_ORIGINAL_SCATTERING (pbb1);
529   ppl_Polyhedron_t so2 = PBB_ORIGINAL_SCATTERING (pbb2);
530
531   if ((pdr_read_p (pdr1) && pdr_read_p (pdr2))
532       || PDR_BASE_OBJECT_SET (pdr1) != PDR_BASE_OBJECT_SET (pdr2)
533       || PDR_NB_SUBSCRIPTS (pdr1) != PDR_NB_SUBSCRIPTS (pdr2))
534     return NULL;
535
536   pddr = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, so1, so2,
537                                 true, true);
538   if (pddr_is_empty (pddr))
539     return NULL;
540
541   return pddr;
542 }
543
544 /* Return true when the data dependence relation between the data
545    references PDR1 belonging to PBB1 and PDR2 is part of a
546    reduction.  */
547
548 static inline bool
549 reduction_dr_1 (poly_bb_p pbb1, poly_dr_p pdr1, poly_dr_p pdr2)
550 {
551   int i;
552   poly_dr_p pdr;
553
554   /* PBB1 should be a reduction PBB.  Reduction PBBs should have only
555      one write.  */
556   gcc_assert (PBB_IS_REDUCTION (pbb1)
557               && number_of_write_pdrs (pbb1) == 1);
558
559   for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr); i++)
560     if (PDR_TYPE (pdr) == PDR_WRITE)
561       break;
562
563   return same_pdr_p (pdr, pdr1) && same_pdr_p (pdr, pdr2);
564 }
565
566 /* Return true when the data dependence relation between the data
567    references PDR1 belonging to PBB1 and PDR2 belonging to PBB2 is
568    part of a reduction.  */
569
570 static inline bool
571 reduction_dr_p (poly_bb_p pbb1, poly_bb_p pbb2,
572                 poly_dr_p pdr1, poly_dr_p pdr2)
573 {
574   if (PBB_IS_REDUCTION (pbb1))
575     return reduction_dr_1 (pbb1, pdr1, pdr2);
576
577   if (PBB_IS_REDUCTION (pbb2))
578     return reduction_dr_1 (pbb2, pdr2, pdr1);
579
580   return false;
581 }
582
583 /* Returns true when the PBB_TRANSFORMED_SCATTERING functions of PBB1
584    and PBB2 respect the data dependences of PBB_ORIGINAL_SCATTERING
585    functions.  */
586
587 static bool
588 graphite_legal_transform_dr (poly_bb_p pbb1, poly_bb_p pbb2,
589                              poly_dr_p pdr1, poly_dr_p pdr2)
590 {
591   ppl_Polyhedron_t st1, st2;
592   ppl_Pointset_Powerset_C_Polyhedron_t po, pt;
593   graphite_dim_t ddim1, otdim1, otdim2, ttdim1, ttdim2;
594   ppl_Pointset_Powerset_C_Polyhedron_t temp;
595   ppl_dimension_type pdim;
596   bool is_empty_p;
597   poly_ddr_p pddr;
598   ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
599   ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
600
601   if (reduction_dr_p (pbb1, pbb2, pdr1, pdr2))
602     return true;
603
604   pddr = pddr_original_scattering (pbb1, pbb2, pdr1, pdr2);
605   if (!pddr)
606     return true;
607
608   po = PDDR_DDP (pddr);
609
610   if (dump_file && (dump_flags & TDF_DETAILS))
611     fprintf (dump_file, "\nloop carries dependency.\n");
612
613   st1 = PBB_TRANSFORMED_SCATTERING (pbb1);
614   st2 = PBB_TRANSFORMED_SCATTERING (pbb2);
615   ddim1 = pbb_dim_iter_domain (pbb1);
616   otdim1 = pbb_nb_scattering_orig (pbb1);
617   otdim2 = pbb_nb_scattering_orig (pbb2);
618   ttdim1 = pbb_nb_scattering_transform (pbb1);
619   ttdim2 = pbb_nb_scattering_transform (pbb2);
620
621   /* Copy the PO polyhedron into the TEMP, so it is not destroyed.
622      Keep in mind, that PO polyhedron might be restored from the cache
623      and should not be modified!  */
624   ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &pdim);
625   ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&temp, pdim, 0);
626   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (temp, po);
627
628   pddr = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, st1, st2,
629                                 false, false);
630   pt = PDDR_DDP (pddr);
631
632   /* Extend PO and PT to have the same dimensions.  */
633   ppl_insert_dimensions_pointset (temp, otdim1, ttdim1);
634   ppl_insert_dimensions_pointset (temp, otdim1 + ttdim1 + ddim1 + otdim2, ttdim2);
635   ppl_insert_dimensions_pointset (pt, 0, otdim1);
636   ppl_insert_dimensions_pointset (pt, otdim1 + ttdim1 + ddim1, otdim2);
637
638   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (temp, pt);
639   is_empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (temp);
640
641   ppl_delete_Pointset_Powerset_C_Polyhedron (temp);
642   free_poly_ddr (pddr);
643
644   return is_empty_p;
645 }
646
647 /* Return true when the data dependence relation for PBB1 and PBB2 is
648    part of a reduction.  */
649
650 static inline bool
651 reduction_ddr_p (poly_bb_p pbb1, poly_bb_p pbb2)
652 {
653   return pbb1 == pbb2 && PBB_IS_REDUCTION (pbb1);
654 }
655
656 /* Iterates over the data references of PBB1 and PBB2 and detect
657    whether the transformed schedule is correct.  */
658
659 static bool
660 graphite_legal_transform_bb (poly_bb_p pbb1, poly_bb_p pbb2)
661 {
662   int i, j;
663   poly_dr_p pdr1, pdr2;
664
665   if (!PBB_PDR_DUPLICATES_REMOVED (pbb1))
666     pbb_remove_duplicate_pdrs (pbb1);
667
668   if (!PBB_PDR_DUPLICATES_REMOVED (pbb2))
669     pbb_remove_duplicate_pdrs (pbb2);
670
671   if (reduction_ddr_p (pbb1, pbb2))
672     return true;
673
674   for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr1); i++)
675     for (j = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), j, pdr2); j++)
676       if (!graphite_legal_transform_dr (pbb1, pbb2, pdr1, pdr2))
677         return false;
678
679   return true;
680 }
681
682 /* Iterates over the SCOP and detect whether the transformed schedule
683    is correct.  */
684
685 bool
686 graphite_legal_transform (scop_p scop)
687 {
688   int i, j;
689   poly_bb_p pbb1, pbb2;
690
691   timevar_push (TV_GRAPHITE_DATA_DEPS);
692
693   for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
694     for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
695       if (!graphite_legal_transform_bb (pbb1, pbb2))
696         {
697           timevar_pop (TV_GRAPHITE_DATA_DEPS);
698           return false;
699         }
700
701   timevar_pop (TV_GRAPHITE_DATA_DEPS);
702   return true;
703 }
704
705 /* Remove all the dimensions except alias information at dimension
706    ALIAS_DIM.  */
707
708 static void
709 build_alias_set_powerset (ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset,
710                           ppl_dimension_type alias_dim)
711 {
712   ppl_dimension_type *ds;
713   ppl_dimension_type access_dim;
714   unsigned i, pos = 0;
715
716   ppl_Pointset_Powerset_C_Polyhedron_space_dimension (alias_powerset,
717                                                       &access_dim);
718   ds = XNEWVEC (ppl_dimension_type, access_dim-1);
719   for (i = 0; i < access_dim; i++)
720     {
721       if (i == alias_dim)
722         continue;
723
724       ds[pos] = i;
725       pos++;
726     }
727
728   ppl_Pointset_Powerset_C_Polyhedron_remove_space_dimensions (alias_powerset,
729                                                               ds,
730                                                               access_dim - 1);
731   free (ds);
732 }
733
734 /* Return true when PDR1 and PDR2 may alias.  */
735
736 static bool
737 poly_drs_may_alias_p (poly_dr_p pdr1, poly_dr_p pdr2)
738 {
739   ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset1, alias_powerset2;
740   ppl_Pointset_Powerset_C_Polyhedron_t accesses1 = PDR_ACCESSES (pdr1);
741   ppl_Pointset_Powerset_C_Polyhedron_t accesses2 = PDR_ACCESSES (pdr2);
742   ppl_dimension_type alias_dim1 = pdr_alias_set_dim (pdr1);
743   ppl_dimension_type alias_dim2 = pdr_alias_set_dim (pdr2);
744   int empty_p;
745
746   ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
747     (&alias_powerset1, accesses1);
748   ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
749     (&alias_powerset2, accesses2);
750
751   build_alias_set_powerset (alias_powerset1, alias_dim1);
752   build_alias_set_powerset (alias_powerset2, alias_dim2);
753
754   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign
755     (alias_powerset1, alias_powerset2);
756
757   empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (alias_powerset1);
758
759   ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset1);
760   ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset2);
761
762   return !empty_p;
763 }
764
765 /* Returns TRUE when the dependence polyhedron between PDR1 and
766    PDR2 represents a loop carried dependence at level LEVEL.  */
767
768 static bool
769 graphite_carried_dependence_level_k (poly_dr_p pdr1, poly_dr_p pdr2,
770                                      int level)
771 {
772   poly_bb_p pbb1 = PDR_PBB (pdr1);
773   poly_bb_p pbb2 = PDR_PBB (pdr2);
774   ppl_Pointset_Powerset_C_Polyhedron_t d1 = PBB_DOMAIN (pbb1);
775   ppl_Pointset_Powerset_C_Polyhedron_t d2 = PBB_DOMAIN (pbb2);
776   ppl_Polyhedron_t so1 = PBB_TRANSFORMED_SCATTERING (pbb1);
777   ppl_Polyhedron_t so2 = PBB_TRANSFORMED_SCATTERING (pbb2);
778   ppl_Pointset_Powerset_C_Polyhedron_t po;
779   ppl_Pointset_Powerset_C_Polyhedron_t eqpp;
780   graphite_dim_t tdim1 = pbb_nb_scattering_transform (pbb1);
781   graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
782   ppl_dimension_type dim;
783   bool empty_p;
784   poly_ddr_p pddr;
785   int obj_base_set1 = PDR_BASE_OBJECT_SET (pdr1);
786   int obj_base_set2 = PDR_BASE_OBJECT_SET (pdr2);
787
788   if ((pdr_read_p (pdr1) && pdr_read_p (pdr2))
789       || !poly_drs_may_alias_p (pdr1, pdr2))
790     return false;
791
792   if (obj_base_set1 != obj_base_set2)
793     return true;
794
795   if (PDR_NB_SUBSCRIPTS (pdr1) != PDR_NB_SUBSCRIPTS (pdr2))
796     return false;
797
798   pddr = dependence_polyhedron (pbb1, pbb2, d1, d2, pdr1, pdr2, so1, so2,
799                                 true, false);
800
801   if (pddr_is_empty (pddr))
802     return false;
803
804   po = PDDR_DDP (pddr);
805   ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &dim);
806   eqpp = build_pairwise_scheduling_inequality (dim, level, tdim1 + ddim1, 1);
807
808   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (eqpp, po);
809   empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (eqpp);
810
811   ppl_delete_Pointset_Powerset_C_Polyhedron (eqpp);
812   return !empty_p;
813 }
814
815 /* Check data dependency between PBB1 and PBB2 at level LEVEL.  */
816
817 bool
818 dependency_between_pbbs_p (poly_bb_p pbb1, poly_bb_p pbb2, int level)
819 {
820   int i, j;
821   poly_dr_p pdr1, pdr2;
822
823   timevar_push (TV_GRAPHITE_DATA_DEPS);
824
825   for (i = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), i, pdr1); i++)
826     for (j = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), j, pdr2); j++)
827       if (graphite_carried_dependence_level_k (pdr1, pdr2, level))
828         {
829           timevar_pop (TV_GRAPHITE_DATA_DEPS);
830           return true;
831         }
832
833   timevar_pop (TV_GRAPHITE_DATA_DEPS);
834   return false;
835 }
836
837 /* Pretty print to FILE all the data dependences of SCoP in DOT
838    format.  */
839
840 static void
841 dot_deps_stmt_1 (FILE *file, scop_p scop)
842 {
843   int i, j, k, l;
844   poly_bb_p pbb1, pbb2;
845   poly_dr_p pdr1, pdr2;
846
847   fputs ("digraph all {\n", file);
848
849   for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
850     for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
851       {
852         for (k = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), k, pdr1); k++)
853           for (l = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), l, pdr2); l++)
854             if (pddr_original_scattering (pbb1, pbb2, pdr1, pdr2))
855               {
856                 fprintf (file, "S%d -> S%d\n",
857                          pbb_index (pbb1), pbb_index (pbb2));
858                 goto done;
859               }
860       done:;
861       }
862
863   fputs ("}\n\n", file);
864 }
865
866 /* Pretty print to FILE all the data dependences of SCoP in DOT
867    format.  */
868
869 static void
870 dot_deps_1 (FILE *file, scop_p scop)
871 {
872   int i, j, k, l;
873   poly_bb_p pbb1, pbb2;
874   poly_dr_p pdr1, pdr2;
875
876   fputs ("digraph all {\n", file);
877
878   for (i = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), i, pbb1); i++)
879     for (j = 0; VEC_iterate (poly_bb_p, SCOP_BBS (scop), j, pbb2); j++)
880       for (k = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb1), k, pdr1); k++)
881         for (l = 0; VEC_iterate (poly_dr_p, PBB_DRS (pbb2), l, pdr2); l++)
882           if (pddr_original_scattering (pbb1, pbb2, pdr1, pdr2))
883             fprintf (file, "S%d_D%d -> S%d_D%d\n",
884                      pbb_index (pbb1), PDR_ID (pdr1),
885                      pbb_index (pbb2), PDR_ID (pdr2));
886
887   fputs ("}\n\n", file);
888 }
889
890 /* Display all the data dependences in SCoP using dotty.  */
891
892 void
893 dot_deps (scop_p scop)
894 {
895   /* When debugging, enable the following code.  This cannot be used
896      in production compilers because it calls "system".  */
897 #if 0
898   int x;
899   FILE *stream = fopen ("/tmp/scopdeps.dot", "w");
900   gcc_assert (stream);
901
902   dot_deps_1 (stream, scop);
903   fclose (stream);
904
905   x = system ("dotty /tmp/scopdeps.dot");
906 #else
907   dot_deps_1 (stderr, scop);
908 #endif
909 }
910
911 /* Display all the statement dependences in SCoP using dotty.  */
912
913 void
914 dot_deps_stmt (scop_p scop)
915 {
916   /* When debugging, enable the following code.  This cannot be used
917      in production compilers because it calls "system".  */
918 #if 0
919   int x;
920   FILE *stream = fopen ("/tmp/scopdeps.dot", "w");
921   gcc_assert (stream);
922
923   dot_deps_stmt_1 (stream, scop);
924   fclose (stream);
925
926   x = system ("dotty /tmp/scopdeps.dot");
927 #else
928   dot_deps_stmt_1 (stderr, scop);
929 #endif
930 }
931
932 #endif