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