OSDN Git Service

* config/interix.opt: New.
[pf3gnuchains/gcc-fork.git] / gcc / graphite-dependences.c
1 /* Data dependence analysis for Graphite.
2    Copyright (C) 2009, 2010 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 "tree-dump.h"
33 #include "timevar.h"
34 #include "cfgloop.h"
35 #include "tree-chrec.h"
36 #include "tree-data-ref.h"
37 #include "tree-scalar-evolution.h"
38 #include "tree-pass.h"
39 #include "domwalk.h"
40 #include "pointer-set.h"
41 #include "gimple.h"
42
43 #ifdef HAVE_cloog
44 #include "ppl_c.h"
45 #include "sese.h"
46 #include "graphite-ppl.h"
47 #include "graphite.h"
48 #include "graphite-poly.h"
49 #include "graphite-dependences.h"
50
51 /* Returns a new polyhedral Data Dependence Relation (DDR).  SOURCE is
52    the source data reference, SINK is the sink data reference.  When
53    the Data Dependence Polyhedron DDP is not NULL or not empty, SOURCE
54    and SINK are in dependence as described by DDP.  */
55
56 static poly_ddr_p
57 new_poly_ddr (poly_dr_p source, poly_dr_p sink,
58               ppl_Pointset_Powerset_C_Polyhedron_t ddp,
59               bool original_scattering_p)
60 {
61   poly_ddr_p pddr = XNEW (struct poly_ddr);
62
63   PDDR_SOURCE (pddr) = source;
64   PDDR_SINK (pddr) = sink;
65   PDDR_DDP (pddr) = ddp;
66   PDDR_ORIGINAL_SCATTERING_P (pddr) = original_scattering_p;
67
68   if (!ddp || ppl_Pointset_Powerset_C_Polyhedron_is_empty (ddp))
69     PDDR_KIND (pddr) = no_dependence;
70   else
71     PDDR_KIND (pddr) = has_dependence;
72
73   return pddr;
74 }
75
76 /* Free the poly_ddr_p P.  */
77
78 void
79 free_poly_ddr (void *p)
80 {
81   poly_ddr_p pddr = (poly_ddr_p) p;
82   ppl_delete_Pointset_Powerset_C_Polyhedron (PDDR_DDP (pddr));
83   free (pddr);
84 }
85
86 /* Comparison function for poly_ddr hash table.  */
87
88 int
89 eq_poly_ddr_p (const void *pddr1, const void *pddr2)
90 {
91   const struct poly_ddr *p1 = (const struct poly_ddr *) pddr1;
92   const struct poly_ddr *p2 = (const struct poly_ddr *) pddr2;
93
94   return (PDDR_SOURCE (p1) == PDDR_SOURCE (p2)
95           && PDDR_SINK (p1) == PDDR_SINK (p2));
96 }
97
98 /* Hash function for poly_ddr hashtable.  */
99
100 hashval_t
101 hash_poly_ddr_p (const void *pddr)
102 {
103   const struct poly_ddr *p = (const struct poly_ddr *) pddr;
104
105   return (hashval_t) ((long) PDDR_SOURCE (p) + (long) PDDR_SINK (p));
106 }
107
108 /* Returns true when PDDR has no dependence.  */
109
110 static bool
111 pddr_is_empty (poly_ddr_p pddr)
112 {
113   if (!pddr)
114     return true;
115
116   gcc_assert (PDDR_KIND (pddr) != unknown_dependence);
117
118   return PDDR_KIND (pddr) == no_dependence ? true : false;
119 }
120
121 /* Prints to FILE the layout of the dependence polyhedron of PDDR:
122
123    T1|I1|T2|I2|S1|S2|G
124
125    with
126    | T1 and T2 the scattering dimensions for PDDR_SOURCE and PDDR_SINK
127    | I1 and I2 the iteration domains
128    | S1 and S2 the subscripts
129    | G the global parameters.  */
130
131 static void
132 print_dependence_polyhedron_layout (FILE *file, poly_ddr_p pddr)
133 {
134   poly_dr_p pdr1 = PDDR_SOURCE (pddr);
135   poly_dr_p pdr2 = PDDR_SINK (pddr);
136   poly_bb_p pbb1 = PDR_PBB (pdr1);
137   poly_bb_p pbb2 = PDR_PBB (pdr2);
138
139   graphite_dim_t i;
140   graphite_dim_t tdim1 = PDDR_ORIGINAL_SCATTERING_P (pddr) ?
141     pbb_nb_scattering_orig (pbb1) : pbb_nb_scattering_transform (pbb1);
142   graphite_dim_t tdim2 = PDDR_ORIGINAL_SCATTERING_P (pddr) ?
143     pbb_nb_scattering_orig (pbb2) : pbb_nb_scattering_transform (pbb2);
144   graphite_dim_t idim1 = pbb_dim_iter_domain (pbb1);
145   graphite_dim_t idim2 = pbb_dim_iter_domain (pbb2);
146   graphite_dim_t sdim1 = PDR_NB_SUBSCRIPTS (pdr1) + 1;
147   graphite_dim_t sdim2 = PDR_NB_SUBSCRIPTS (pdr2) + 1;
148   graphite_dim_t gdim = scop_nb_params (PBB_SCOP (pbb1));
149
150   fprintf (file, "#  eq");
151
152   for (i = 0; i < tdim1; i++)
153     fprintf (file, "   t1_%d", (int) i);
154   for (i = 0; i < idim1; i++)
155     fprintf (file, "   i1_%d", (int) i);
156   for (i = 0; i < tdim2; i++)
157     fprintf (file, "   t2_%d", (int) i);
158   for (i = 0; i < idim2; i++)
159     fprintf (file, "   i2_%d", (int) i);
160   for (i = 0; i < sdim1; i++)
161     fprintf (file, "   s1_%d", (int) i);
162   for (i = 0; i < sdim2; i++)
163     fprintf (file, "   s2_%d", (int) i);
164   for (i = 0; i < gdim; i++)
165     fprintf (file, "    g_%d", (int) i);
166
167   fprintf (file, "    cst\n");
168 }
169
170 /* Prints to FILE the poly_ddr_p PDDR.  */
171
172 void
173 print_pddr (FILE *file, poly_ddr_p pddr)
174 {
175   fprintf (file, "pddr (kind: ");
176
177   if (PDDR_KIND (pddr) == unknown_dependence)
178     fprintf (file, "unknown_dependence");
179   else if (PDDR_KIND (pddr) == no_dependence)
180     fprintf (file, "no_dependence");
181   else if (PDDR_KIND (pddr) == has_dependence)
182     fprintf (file, "has_dependence");
183
184   fprintf (file, "\n  source ");
185   print_pdr (file, PDDR_SOURCE (pddr), 2);
186
187   fprintf (file, "\n  sink ");
188   print_pdr (file, PDDR_SINK (pddr), 2);
189
190   if (PDDR_KIND (pddr) == has_dependence)
191     {
192       fprintf (file, "\n  dependence polyhedron (\n");
193       print_dependence_polyhedron_layout (file, pddr);
194       ppl_print_powerset_matrix (file, PDDR_DDP (pddr));
195       fprintf (file, ")\n");
196     }
197
198   fprintf (file, ")\n");
199 }
200
201 /* Prints to STDERR the poly_ddr_p PDDR.  */
202
203 DEBUG_FUNCTION void
204 debug_pddr (poly_ddr_p pddr)
205 {
206   print_pddr (stderr, pddr);
207 }
208
209
210 /* Remove all the dimensions except alias information at dimension
211    ALIAS_DIM.  */
212
213 static void
214 build_alias_set_powerset (ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset,
215                           ppl_dimension_type alias_dim)
216 {
217   ppl_dimension_type *ds;
218   ppl_dimension_type access_dim;
219   unsigned i, pos = 0;
220
221   ppl_Pointset_Powerset_C_Polyhedron_space_dimension (alias_powerset,
222                                                       &access_dim);
223   ds = XNEWVEC (ppl_dimension_type, access_dim-1);
224   for (i = 0; i < access_dim; i++)
225     {
226       if (i == alias_dim)
227         continue;
228
229       ds[pos] = i;
230       pos++;
231     }
232
233   ppl_Pointset_Powerset_C_Polyhedron_remove_space_dimensions (alias_powerset,
234                                                               ds,
235                                                               access_dim - 1);
236   free (ds);
237 }
238
239 /* Return true when PDR1 and PDR2 may alias.  */
240
241 static bool
242 poly_drs_may_alias_p (poly_dr_p pdr1, poly_dr_p pdr2)
243 {
244   ppl_Pointset_Powerset_C_Polyhedron_t alias_powerset1, alias_powerset2;
245   ppl_Pointset_Powerset_C_Polyhedron_t accesses1 = PDR_ACCESSES (pdr1);
246   ppl_Pointset_Powerset_C_Polyhedron_t accesses2 = PDR_ACCESSES (pdr2);
247   ppl_dimension_type alias_dim1 = pdr_alias_set_dim (pdr1);
248   ppl_dimension_type alias_dim2 = pdr_alias_set_dim (pdr2);
249   int empty_p;
250
251   ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
252     (&alias_powerset1, accesses1);
253   ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
254     (&alias_powerset2, accesses2);
255
256   build_alias_set_powerset (alias_powerset1, alias_dim1);
257   build_alias_set_powerset (alias_powerset2, alias_dim2);
258
259   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign
260     (alias_powerset1, alias_powerset2);
261
262   empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (alias_powerset1);
263
264   ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset1);
265   ppl_delete_Pointset_Powerset_C_Polyhedron (alias_powerset2);
266
267   return !empty_p;
268 }
269
270 /* Swap [cut0, ..., cut1] to the end of DR: "a CUT0 b CUT1 c" is
271    transformed into "a CUT0 c CUT1' b"
272
273    Add NB0 zeros before "a":  "00...0 a CUT0 c CUT1' b"
274    Add NB1 zeros between "a" and "c":  "00...0 a 00...0 c CUT1' b"
275    Add DIM - NB0 - NB1 - PDIM zeros between "c" and "b":
276    "00...0 a 00...0 c 00...0 b".  */
277
278 static ppl_Pointset_Powerset_C_Polyhedron_t
279 map_dr_into_dep_poly (graphite_dim_t dim,
280                       ppl_Pointset_Powerset_C_Polyhedron_t dr,
281                       graphite_dim_t cut0, graphite_dim_t cut1,
282                       graphite_dim_t nb0, graphite_dim_t nb1)
283 {
284   ppl_dimension_type pdim;
285   ppl_dimension_type *map;
286   ppl_Pointset_Powerset_C_Polyhedron_t res;
287   ppl_dimension_type i;
288
289   ppl_new_Pointset_Powerset_C_Polyhedron_from_Pointset_Powerset_C_Polyhedron
290     (&res, dr);
291   ppl_Pointset_Powerset_C_Polyhedron_space_dimension (res, &pdim);
292
293   map = (ppl_dimension_type *) XNEWVEC (ppl_dimension_type, pdim);
294
295   /* First mapping: move 'g' vector to right position.  */
296   for (i = 0; i < cut0; i++)
297     map[i] = i;
298
299   for (i = cut0; i < cut1; i++)
300     map[i] = pdim - cut1 + i;
301
302   for (i = cut1; i < pdim; i++)
303     map[i] = cut0 + i - cut1;
304
305   ppl_Pointset_Powerset_C_Polyhedron_map_space_dimensions (res, map, pdim);
306   free (map);
307
308   /* After swapping 's' and 'g' vectors, we have to update a new cut.  */
309   cut1 = pdim - cut1 + cut0;
310
311   ppl_insert_dimensions_pointset (res, 0, nb0);
312   ppl_insert_dimensions_pointset (res, nb0 + cut0, nb1);
313   ppl_insert_dimensions_pointset (res, nb0 + nb1 + cut1,
314                                   dim - nb0 - nb1 - pdim);
315
316   return res;
317 }
318
319 /* Builds subscript equality constraints.  */
320
321 static ppl_Pointset_Powerset_C_Polyhedron_t
322 dr_equality_constraints (graphite_dim_t dim,
323                          graphite_dim_t pos, graphite_dim_t nb_subscripts)
324 {
325   ppl_Polyhedron_t eqs;
326   ppl_Pointset_Powerset_C_Polyhedron_t res;
327   graphite_dim_t i;
328
329   ppl_new_C_Polyhedron_from_space_dimension (&eqs, dim, 0);
330
331   for (i = 0; i < nb_subscripts; i++)
332     {
333       ppl_Constraint_t cstr
334         = ppl_build_relation (dim, pos + i, pos + i + nb_subscripts,
335                               0, PPL_CONSTRAINT_TYPE_EQUAL);
336       ppl_Polyhedron_add_constraint (eqs, cstr);
337       ppl_delete_Constraint (cstr);
338     }
339
340   ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, eqs);
341   ppl_delete_Polyhedron (eqs);
342   return res;
343 }
344
345 /* Builds scheduling inequality constraints: when DIRECTION is
346    1 builds a GE constraint,
347    0 builds an EQ constraint,
348    -1 builds a LE constraint.  */
349
350 static ppl_Pointset_Powerset_C_Polyhedron_t
351 build_pairwise_scheduling (graphite_dim_t dim,
352                            graphite_dim_t pos,
353                            graphite_dim_t offset,
354                            int direction)
355 {
356   ppl_Pointset_Powerset_C_Polyhedron_t res;
357   ppl_Polyhedron_t equalities;
358   ppl_Constraint_t cstr;
359
360   ppl_new_C_Polyhedron_from_space_dimension (&equalities, dim, 0);
361
362   switch (direction)
363     {
364     case -1:
365       cstr = ppl_build_relation (dim, pos, pos + offset, 1,
366                                  PPL_CONSTRAINT_TYPE_LESS_OR_EQUAL);
367       break;
368
369     case 0:
370       cstr = ppl_build_relation (dim, pos, pos + offset, 0,
371                                  PPL_CONSTRAINT_TYPE_EQUAL);
372       break;
373
374     case 1:
375       cstr = ppl_build_relation (dim, pos, pos + offset, -1,
376                                  PPL_CONSTRAINT_TYPE_GREATER_OR_EQUAL);
377       break;
378
379     default:
380       gcc_unreachable ();
381     }
382
383   ppl_Polyhedron_add_constraint (equalities, cstr);
384   ppl_delete_Constraint (cstr);
385
386   ppl_new_Pointset_Powerset_C_Polyhedron_from_C_Polyhedron (&res, equalities);
387   ppl_delete_Polyhedron (equalities);
388   return res;
389 }
390
391 /* Add to a non empty polyhedron BAG the precedence constraints for
392    the lexicographical comparison of time vectors in BAG following the
393    lexicographical order.  DIM is the dimension of the polyhedron BAG.
394    TDIM is the number of loops common to the two statements that are
395    compared lexicographically, i.e. the number of loops containing
396    both statements.  OFFSET is the number of dimensions needed to
397    represent the first statement, i.e. dimT1 + dimI1 in the layout of
398    the BAG polyhedron: T1|I1|T2|I2|S1|S2|G.  When DIRECTION is set to
399    1, compute the direct dependence from PDR1 to PDR2, and when
400    DIRECTION is -1, compute the reversed dependence relation, from
401    PDR2 to PDR1.  */
402
403 static ppl_Pointset_Powerset_C_Polyhedron_t
404 build_lexicographical_constraint (ppl_Pointset_Powerset_C_Polyhedron_t bag,
405                                   graphite_dim_t dim,
406                                   graphite_dim_t tdim,
407                                   graphite_dim_t offset,
408                                   int direction)
409 {
410   graphite_dim_t i;
411   ppl_Pointset_Powerset_C_Polyhedron_t res, lex;
412
413   ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&res, dim, 1);
414
415   lex = build_pairwise_scheduling (dim, 0, offset, direction);
416   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (lex, bag);
417
418   if (!ppl_Pointset_Powerset_C_Polyhedron_is_empty (lex))
419     ppl_Pointset_Powerset_C_Polyhedron_upper_bound_assign (res, lex);
420
421   ppl_delete_Pointset_Powerset_C_Polyhedron (lex);
422
423   for (i = 0; i < tdim - 1; i++)
424     {
425       ppl_Pointset_Powerset_C_Polyhedron_t sceq;
426
427       sceq = build_pairwise_scheduling (dim, i, offset, 0);
428       ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (bag, sceq);
429       ppl_delete_Pointset_Powerset_C_Polyhedron (sceq);
430
431       lex = build_pairwise_scheduling (dim, i + 1, offset, direction);
432       ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (lex, bag);
433
434       if (!ppl_Pointset_Powerset_C_Polyhedron_is_empty (lex))
435         ppl_Pointset_Powerset_C_Polyhedron_upper_bound_assign (res, lex);
436
437       ppl_delete_Pointset_Powerset_C_Polyhedron (lex);
438     }
439
440   return res;
441 }
442
443 /* Build the dependence polyhedron for data references PDR1 and PDR2.
444    The layout of the dependence polyhedron is:
445
446    T1|I1|T2|I2|S1|S2|G
447
448    with
449    | T1 and T2 the scattering dimensions for PDR1 and PDR2
450    | I1 and I2 the iteration domains
451    | S1 and S2 the subscripts
452    | G the global parameters.
453
454    When DIRECTION is set to 1, compute the direct dependence from PDR1
455    to PDR2, and when DIRECTION is -1, compute the reversed dependence
456    relation, from PDR2 to PDR1.  */
457
458 static ppl_Pointset_Powerset_C_Polyhedron_t
459 dependence_polyhedron_1 (poly_dr_p pdr1, poly_dr_p pdr2,
460                          int direction, bool original_scattering_p)
461 {
462   poly_bb_p pbb1 = PDR_PBB (pdr1);
463   poly_bb_p pbb2 = PDR_PBB (pdr2);
464   scop_p scop = PBB_SCOP (pbb1);
465   graphite_dim_t tdim1 = original_scattering_p ?
466     pbb_nb_scattering_orig (pbb1) : pbb_nb_scattering_transform (pbb1);
467   graphite_dim_t tdim2 = original_scattering_p ?
468     pbb_nb_scattering_orig (pbb2) : pbb_nb_scattering_transform (pbb2);
469   graphite_dim_t ddim1 = pbb_dim_iter_domain (pbb1);
470   graphite_dim_t ddim2 = pbb_dim_iter_domain (pbb2);
471   graphite_dim_t sdim1 = PDR_NB_SUBSCRIPTS (pdr1) + 1;
472   graphite_dim_t sdim2 = PDR_NB_SUBSCRIPTS (pdr2) + 1;
473   graphite_dim_t gdim = scop_nb_params (scop);
474   graphite_dim_t dim1 = pdr_dim (pdr1);
475   graphite_dim_t dim2 = pdr_dim (pdr2);
476   graphite_dim_t dim = tdim1 + tdim2 + dim1 + dim2 - gdim;
477   ppl_Pointset_Powerset_C_Polyhedron_t res;
478   ppl_Pointset_Powerset_C_Polyhedron_t idr1, idr2;
479   ppl_Pointset_Powerset_C_Polyhedron_t sc1, sc2, dreq;
480
481   gcc_assert (PBB_SCOP (pbb1) == PBB_SCOP (pbb2));
482
483   combine_context_id_scat (&sc1, pbb1, original_scattering_p);
484   combine_context_id_scat (&sc2, pbb2, original_scattering_p);
485
486   ppl_insert_dimensions_pointset (sc1, tdim1 + ddim1,
487                                   tdim2 + ddim2 + sdim1 + sdim2);
488
489   ppl_insert_dimensions_pointset (sc2, 0, tdim1 + ddim1);
490   ppl_insert_dimensions_pointset (sc2, tdim1 + ddim1 + tdim2 + ddim2,
491                                   sdim1 + sdim2);
492
493   idr1 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr1), ddim1, ddim1 + gdim,
494                                tdim1, tdim2 + ddim2);
495   idr2 = map_dr_into_dep_poly (dim, PDR_ACCESSES (pdr2), ddim2, ddim2 + gdim,
496                                tdim1 + ddim1 + tdim2, sdim1);
497
498   /* Now add the subscript equalities.  */
499   dreq = dr_equality_constraints (dim, tdim1 + ddim1 + tdim2 + ddim2, sdim1);
500
501   ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&res, dim, 0);
502   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, sc1);
503   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, sc2);
504   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr1);
505   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, idr2);
506   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (res, dreq);
507   ppl_delete_Pointset_Powerset_C_Polyhedron (sc1);
508   ppl_delete_Pointset_Powerset_C_Polyhedron (sc2);
509   ppl_delete_Pointset_Powerset_C_Polyhedron (idr1);
510   ppl_delete_Pointset_Powerset_C_Polyhedron (idr2);
511   ppl_delete_Pointset_Powerset_C_Polyhedron (dreq);
512
513   if (!ppl_Pointset_Powerset_C_Polyhedron_is_empty (res))
514     {
515       ppl_Pointset_Powerset_C_Polyhedron_t lex =
516         build_lexicographical_constraint (res, dim, MIN (tdim1, tdim2),
517                                           tdim1 + ddim1, direction);
518       ppl_delete_Pointset_Powerset_C_Polyhedron (res);
519       res = lex;
520     }
521
522   return res;
523 }
524
525 /* Build the dependence polyhedron for data references PDR1 and PDR2.
526    If possible use already cached information.
527
528    When DIRECTION is set to 1, compute the direct dependence from PDR1
529    to PDR2, and when DIRECTION is -1, compute the reversed dependence
530    relation, from PDR2 to PDR1.  */
531
532 static poly_ddr_p
533 dependence_polyhedron (poly_dr_p pdr1, poly_dr_p pdr2,
534                        int direction, bool original_scattering_p)
535 {
536   PTR *x = NULL;
537   poly_ddr_p res;
538   ppl_Pointset_Powerset_C_Polyhedron_t ddp;
539
540   /* Return the PDDR from the cache if it already has been computed.  */
541   if (original_scattering_p)
542     {
543       struct poly_ddr tmp;
544       scop_p scop = PBB_SCOP (PDR_PBB (pdr1));
545
546       tmp.source = pdr1;
547       tmp.sink = pdr2;
548       x = htab_find_slot (SCOP_ORIGINAL_PDDRS (scop),
549                           &tmp, INSERT);
550
551       if (x && *x)
552         return (poly_ddr_p) *x;
553     }
554
555   if ((pdr_read_p (pdr1) && pdr_read_p (pdr2))
556       || PDR_BASE_OBJECT_SET (pdr1) != PDR_BASE_OBJECT_SET (pdr2)
557       || PDR_NB_SUBSCRIPTS (pdr1) != PDR_NB_SUBSCRIPTS (pdr2)
558       || !poly_drs_may_alias_p (pdr1, pdr2))
559     ddp = NULL;
560   else
561     ddp = dependence_polyhedron_1 (pdr1, pdr2, direction,
562                                    original_scattering_p);
563
564   res = new_poly_ddr (pdr1, pdr2, ddp, original_scattering_p);
565
566   if (!(pdr_read_p (pdr1) && pdr_read_p (pdr2))
567       && PDR_BASE_OBJECT_SET (pdr1) != PDR_BASE_OBJECT_SET (pdr2)
568       && poly_drs_may_alias_p (pdr1, pdr2))
569     PDDR_KIND (res) = unknown_dependence;
570
571   if (original_scattering_p)
572     *x = res;
573
574   return res;
575 }
576
577 /* Return true when the data dependence relation between the data
578    references PDR1 belonging to PBB1 and PDR2 is part of a
579    reduction.  */
580
581 static inline bool
582 reduction_dr_1 (poly_bb_p pbb1, poly_dr_p pdr1, poly_dr_p pdr2)
583 {
584   int i;
585   poly_dr_p pdr;
586
587   FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb1), i, pdr)
588     if (PDR_TYPE (pdr) == PDR_WRITE)
589       break;
590
591   return same_pdr_p (pdr, pdr1) && same_pdr_p (pdr, pdr2);
592 }
593
594 /* Return true when the data dependence relation between the data
595    references PDR1 belonging to PBB1 and PDR2 belonging to PBB2 is
596    part of a reduction.  */
597
598 static inline bool
599 reduction_dr_p (poly_dr_p pdr1, poly_dr_p pdr2)
600 {
601   poly_bb_p pbb1 = PDR_PBB (pdr1);
602   poly_bb_p pbb2 = PDR_PBB (pdr2);
603
604   if (PBB_IS_REDUCTION (pbb1))
605     return reduction_dr_1 (pbb1, pdr1, pdr2);
606
607   if (PBB_IS_REDUCTION (pbb2))
608     return reduction_dr_1 (pbb2, pdr2, pdr1);
609
610   return false;
611 }
612
613 /* Returns true when the PBB_TRANSFORMED_SCATTERING functions of PBB1
614    and PBB2 respect the data dependences of PBB_ORIGINAL_SCATTERING
615    functions.  */
616
617 static bool
618 graphite_legal_transform_dr (poly_dr_p pdr1, poly_dr_p pdr2)
619 {
620   ppl_Pointset_Powerset_C_Polyhedron_t po, pt;
621   graphite_dim_t ddim1, otdim1, otdim2, ttdim1, ttdim2;
622   ppl_Pointset_Powerset_C_Polyhedron_t po_temp;
623   ppl_dimension_type pdim;
624   bool is_empty_p;
625   poly_ddr_p opddr, tpddr;
626   poly_bb_p pbb1, pbb2;
627
628   if (reduction_dr_p (pdr1, pdr2))
629     return true;
630
631   /* We build the reverse dependence relation for the transformed
632      scattering, such that when we intersect it with the original PO,
633      we get an empty intersection when the transform is legal:
634      i.e. the transform should reverse no dependences, and so PT, the
635      reversed transformed PDDR, should have no constraint from PO.  */
636   opddr = dependence_polyhedron (pdr1, pdr2, 1, true);
637
638   if (PDDR_KIND (opddr) == unknown_dependence)
639     return false;
640
641     /* There are no dependences between PDR1 and PDR2 in the original
642        version of the program, or after the transform, so the
643        transform is legal.  */
644   if (pddr_is_empty (opddr))
645     return true;
646
647   tpddr = dependence_polyhedron (pdr1, pdr2, -1, false);
648
649   if (PDDR_KIND (tpddr) == unknown_dependence)
650     {
651       free_poly_ddr (tpddr);
652       return false;
653     }
654
655   if (pddr_is_empty (tpddr))
656     {
657       free_poly_ddr (tpddr);
658       return true;
659     }
660
661   po = PDDR_DDP (opddr);
662   pt = PDDR_DDP (tpddr);
663
664   /* Copy PO into PO_TEMP, such that PO is not destroyed.  PO is
665      stored in a cache and should not be modified or freed.  */
666   ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &pdim);
667   ppl_new_Pointset_Powerset_C_Polyhedron_from_space_dimension (&po_temp,
668                                                                pdim, 0);
669   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (po_temp, po);
670
671   /* Extend PO and PT to have the same dimensions.  */
672   pbb1 = PDR_PBB (pdr1);
673   pbb2 = PDR_PBB (pdr2);
674   ddim1 = pbb_dim_iter_domain (pbb1);
675   otdim1 = pbb_nb_scattering_orig (pbb1);
676   otdim2 = pbb_nb_scattering_orig (pbb2);
677   ttdim1 = pbb_nb_scattering_transform (pbb1);
678   ttdim2 = pbb_nb_scattering_transform (pbb2);
679   ppl_insert_dimensions_pointset (po_temp, otdim1, ttdim1);
680   ppl_insert_dimensions_pointset (po_temp, otdim1 + ttdim1 + ddim1 + otdim2,
681                                   ttdim2);
682   ppl_insert_dimensions_pointset (pt, 0, otdim1);
683   ppl_insert_dimensions_pointset (pt, otdim1 + ttdim1 + ddim1, otdim2);
684
685   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (po_temp, pt);
686   is_empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (po_temp);
687
688   ppl_delete_Pointset_Powerset_C_Polyhedron (po_temp);
689   free_poly_ddr (tpddr);
690
691   if (dump_file && (dump_flags & TDF_DETAILS))
692     fprintf (dump_file, "\nloop carries dependency.\n");
693
694   return is_empty_p;
695 }
696
697 /* Return true when the data dependence relation for PBB1 and PBB2 is
698    part of a reduction.  */
699
700 static inline bool
701 reduction_ddr_p (poly_bb_p pbb1, poly_bb_p pbb2)
702 {
703   return pbb1 == pbb2 && PBB_IS_REDUCTION (pbb1);
704 }
705
706 /* Iterates over the data references of PBB1 and PBB2 and detect
707    whether the transformed schedule is correct.  */
708
709 static bool
710 graphite_legal_transform_bb (poly_bb_p pbb1, poly_bb_p pbb2)
711 {
712   int i, j;
713   poly_dr_p pdr1, pdr2;
714
715   if (!PBB_PDR_DUPLICATES_REMOVED (pbb1))
716     pbb_remove_duplicate_pdrs (pbb1);
717
718   if (!PBB_PDR_DUPLICATES_REMOVED (pbb2))
719     pbb_remove_duplicate_pdrs (pbb2);
720
721   if (reduction_ddr_p (pbb1, pbb2))
722     return true;
723
724   FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb1), i, pdr1)
725     FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb2), j, pdr2)
726       if (!graphite_legal_transform_dr (pdr1, pdr2))
727         return false;
728
729   return true;
730 }
731
732 /* Iterates over the SCOP and detect whether the transformed schedule
733    is correct.  */
734
735 bool
736 graphite_legal_transform (scop_p scop)
737 {
738   int i, j;
739   poly_bb_p pbb1, pbb2;
740
741   timevar_push (TV_GRAPHITE_DATA_DEPS);
742
743   FOR_EACH_VEC_ELT (poly_bb_p, SCOP_BBS (scop), i, pbb1)
744     FOR_EACH_VEC_ELT (poly_bb_p, SCOP_BBS (scop), j, pbb2)
745       if (!graphite_legal_transform_bb (pbb1, pbb2))
746         {
747           timevar_pop (TV_GRAPHITE_DATA_DEPS);
748           return false;
749         }
750
751   timevar_pop (TV_GRAPHITE_DATA_DEPS);
752   return true;
753 }
754
755 /* Returns TRUE when the dependence polyhedron between PDR1 and
756    PDR2 represents a loop carried dependence at level LEVEL.  */
757
758 static bool
759 graphite_carried_dependence_level_k (poly_dr_p pdr1, poly_dr_p pdr2,
760                                      int level)
761 {
762   ppl_Pointset_Powerset_C_Polyhedron_t po;
763   ppl_Pointset_Powerset_C_Polyhedron_t eqpp;
764   graphite_dim_t tdim1 = pbb_nb_scattering_transform (PDR_PBB (pdr1));
765   graphite_dim_t ddim1 = pbb_dim_iter_domain (PDR_PBB (pdr1));
766   ppl_dimension_type dim;
767   bool empty_p;
768   poly_ddr_p pddr = dependence_polyhedron (pdr1, pdr2, 1, false);
769
770   if (PDDR_KIND (pddr) == unknown_dependence)
771     {
772       free_poly_ddr (pddr);
773       return true;
774     }
775
776   if (pddr_is_empty (pddr))
777     {
778       free_poly_ddr (pddr);
779       return false;
780     }
781
782   po = PDDR_DDP (pddr);
783   ppl_Pointset_Powerset_C_Polyhedron_space_dimension (po, &dim);
784   eqpp = build_pairwise_scheduling (dim, level, tdim1 + ddim1, 1);
785
786   ppl_Pointset_Powerset_C_Polyhedron_intersection_assign (eqpp, po);
787   empty_p = ppl_Pointset_Powerset_C_Polyhedron_is_empty (eqpp);
788
789   ppl_delete_Pointset_Powerset_C_Polyhedron (eqpp);
790   free_poly_ddr (pddr);
791
792   return !empty_p;
793 }
794
795 /* Check data dependency between PBB1 and PBB2 at level LEVEL.  */
796
797 bool
798 dependency_between_pbbs_p (poly_bb_p pbb1, poly_bb_p pbb2, int level)
799 {
800   int i, j;
801   poly_dr_p pdr1, pdr2;
802
803   timevar_push (TV_GRAPHITE_DATA_DEPS);
804
805   FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb1), i, pdr1)
806     FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb2), j, pdr2)
807       if (graphite_carried_dependence_level_k (pdr1, pdr2, level))
808         {
809           timevar_pop (TV_GRAPHITE_DATA_DEPS);
810           return true;
811         }
812
813   timevar_pop (TV_GRAPHITE_DATA_DEPS);
814   return false;
815 }
816
817 /* Pretty print to FILE all the original data dependences of SCoP in
818    DOT format.  */
819
820 static void
821 dot_original_deps_stmt_1 (FILE *file, scop_p scop)
822 {
823   int i, j, k, l;
824   poly_bb_p pbb1, pbb2;
825   poly_dr_p pdr1, pdr2;
826
827   FOR_EACH_VEC_ELT (poly_bb_p, SCOP_BBS (scop), i, pbb1)
828     FOR_EACH_VEC_ELT (poly_bb_p, SCOP_BBS (scop), j, pbb2)
829       {
830         FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb1), k, pdr1)
831           FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb2), l, pdr2)
832             if (!pddr_is_empty (dependence_polyhedron (pdr1, pdr2, 1, true)))
833               {
834                 fprintf (file, "OS%d -> OS%d\n",
835                          pbb_index (pbb1), pbb_index (pbb2));
836                 goto done;
837               }
838       done:;
839       }
840 }
841
842 /* Pretty print to FILE all the transformed data dependences of SCoP in
843    DOT format.  */
844
845 static void
846 dot_transformed_deps_stmt_1 (FILE *file, scop_p scop)
847 {
848   int i, j, k, l;
849   poly_bb_p pbb1, pbb2;
850   poly_dr_p pdr1, pdr2;
851
852   FOR_EACH_VEC_ELT (poly_bb_p, SCOP_BBS (scop), i, pbb1)
853     FOR_EACH_VEC_ELT (poly_bb_p, SCOP_BBS (scop), j, pbb2)
854       {
855         FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb1), k, pdr1)
856           FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb2), l, pdr2)
857             {
858               poly_ddr_p pddr = dependence_polyhedron (pdr1, pdr2, 1, false);
859
860               if (!pddr_is_empty (pddr))
861                 {
862                   fprintf (file, "TS%d -> TS%d\n",
863                            pbb_index (pbb1), pbb_index (pbb2));
864
865                   free_poly_ddr (pddr);
866                   goto done;
867                 }
868
869               free_poly_ddr (pddr);
870             }
871       done:;
872       }
873 }
874
875
876 /* Pretty print to FILE all the data dependences of SCoP in DOT
877    format.  */
878
879 static void
880 dot_deps_stmt_1 (FILE *file, scop_p scop)
881 {
882   fputs ("digraph all {\n", file);
883
884   dot_original_deps_stmt_1 (file, scop);
885   dot_transformed_deps_stmt_1 (file, scop);
886
887   fputs ("}\n\n", file);
888 }
889
890 /* Pretty print to FILE all the original data dependences of SCoP in
891    DOT format.  */
892
893 static void
894 dot_original_deps (FILE *file, scop_p scop)
895 {
896   int i, j, k, l;
897   poly_bb_p pbb1, pbb2;
898   poly_dr_p pdr1, pdr2;
899
900   FOR_EACH_VEC_ELT (poly_bb_p, SCOP_BBS (scop), i, pbb1)
901     FOR_EACH_VEC_ELT (poly_bb_p, SCOP_BBS (scop), j, pbb2)
902       FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb1), k, pdr1)
903         FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb2), l, pdr2)
904           if (!pddr_is_empty (dependence_polyhedron (pdr1, pdr2, 1, true)))
905             fprintf (file, "OS%d_D%d -> OS%d_D%d\n",
906                      pbb_index (pbb1), PDR_ID (pdr1),
907                      pbb_index (pbb2), PDR_ID (pdr2));
908 }
909
910 /* Pretty print to FILE all the transformed data dependences of SCoP in
911    DOT format.  */
912
913 static void
914 dot_transformed_deps (FILE *file, scop_p scop)
915 {
916   int i, j, k, l;
917   poly_bb_p pbb1, pbb2;
918   poly_dr_p pdr1, pdr2;
919
920   FOR_EACH_VEC_ELT (poly_bb_p, SCOP_BBS (scop), i, pbb1)
921     FOR_EACH_VEC_ELT (poly_bb_p, SCOP_BBS (scop), j, pbb2)
922       FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb1), k, pdr1)
923         FOR_EACH_VEC_ELT (poly_dr_p, PBB_DRS (pbb2), l, pdr2)
924           {
925             poly_ddr_p pddr = dependence_polyhedron (pdr1, pdr2, 1, false);
926
927             if (!pddr_is_empty (pddr))
928               fprintf (file, "TS%d_D%d -> TS%d_D%d\n",
929                        pbb_index (pbb1), PDR_ID (pdr1),
930                        pbb_index (pbb2), PDR_ID (pdr2));
931
932             free_poly_ddr (pddr);
933           }
934 }
935
936 /* Pretty print to FILE all the data dependences of SCoP in DOT
937    format.  */
938
939 static void
940 dot_deps_1 (FILE *file, scop_p scop)
941 {
942   fputs ("digraph all {\n", file);
943
944   dot_original_deps (file, scop);
945   dot_transformed_deps (file, scop);
946
947   fputs ("}\n\n", file);
948 }
949
950 /* Display all the data dependences in SCoP using dotty.  */
951
952 DEBUG_FUNCTION void
953 dot_deps (scop_p scop)
954 {
955   /* When debugging, enable the following code.  This cannot be used
956      in production compilers because it calls "system".  */
957 #if 0
958   FILE *stream = fopen ("/tmp/scopdeps.dot", "w");
959   gcc_assert (stream);
960
961   dot_deps_1 (stream, scop);
962   fclose (stream);
963
964   system ("dotty /tmp/scopdeps.dot &");
965 #else
966   dot_deps_1 (stderr, scop);
967 #endif
968 }
969
970 /* Display all the statement dependences in SCoP using dotty.  */
971
972 DEBUG_FUNCTION void
973 dot_deps_stmt (scop_p scop)
974 {
975   /* When debugging, enable the following code.  This cannot be used
976      in production compilers because it calls "system".  */
977 #if 0
978   FILE *stream = fopen ("/tmp/scopdeps.dot", "w");
979   gcc_assert (stream);
980
981   dot_deps_stmt_1 (stream, scop);
982   fclose (stream);
983
984   system ("dotty /tmp/scopdeps.dot &");
985 #else
986   dot_deps_stmt_1 (stderr, scop);
987 #endif
988 }
989
990 #endif