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