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