coretypes.h: Include machmode.h...
[gcc.git] / gcc / graphite-dependences.c
1 /* Data dependence analysis for Graphite.
2 Copyright (C) 2009-2015 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
24 #ifdef HAVE_isl
25 #include <isl/set.h>
26 #include <isl/map.h>
27 #include <isl/union_map.h>
28 #include <isl/flow.h>
29 #include <isl/constraint.h>
30 #endif
31
32 #include "system.h"
33 #include "coretypes.h"
34 #include "hash-set.h"
35 #include "vec.h"
36 #include "input.h"
37 #include "alias.h"
38 #include "symtab.h"
39 #include "options.h"
40 #include "inchash.h"
41 #include "tree.h"
42 #include "fold-const.h"
43 #include "predict.h"
44 #include "tm.h"
45 #include "hard-reg-set.h"
46 #include "input.h"
47 #include "function.h"
48 #include "dominance.h"
49 #include "cfg.h"
50 #include "basic-block.h"
51 #include "tree-ssa-alias.h"
52 #include "internal-fn.h"
53 #include "gimple-expr.h"
54 #include "is-a.h"
55 #include "gimple.h"
56 #include "gimple-iterator.h"
57 #include "tree-ssa-loop.h"
58 #include "tree-pass.h"
59 #include "cfgloop.h"
60 #include "tree-chrec.h"
61 #include "tree-data-ref.h"
62 #include "tree-scalar-evolution.h"
63 #include "sese.h"
64
65 #ifdef HAVE_isl
66 #include "graphite-poly.h"
67
68 isl_union_map *
69 scop_get_dependences (scop_p scop)
70 {
71 isl_union_map *dependences;
72
73 if (!scop->must_raw)
74 compute_deps (scop, SCOP_BBS (scop),
75 &scop->must_raw, &scop->may_raw,
76 &scop->must_raw_no_source, &scop->may_raw_no_source,
77 &scop->must_war, &scop->may_war,
78 &scop->must_war_no_source, &scop->may_war_no_source,
79 &scop->must_waw, &scop->may_waw,
80 &scop->must_waw_no_source, &scop->may_waw_no_source);
81
82 dependences = isl_union_map_copy (scop->must_raw);
83 dependences = isl_union_map_union (dependences,
84 isl_union_map_copy (scop->must_war));
85 dependences = isl_union_map_union (dependences,
86 isl_union_map_copy (scop->must_waw));
87 dependences = isl_union_map_union (dependences,
88 isl_union_map_copy (scop->may_raw));
89 dependences = isl_union_map_union (dependences,
90 isl_union_map_copy (scop->may_war));
91 dependences = isl_union_map_union (dependences,
92 isl_union_map_copy (scop->may_waw));
93
94 return dependences;
95 }
96
97 /* Add the constraints from the set S to the domain of MAP. */
98
99 static isl_map *
100 constrain_domain (isl_map *map, isl_set *s)
101 {
102 isl_space *d = isl_map_get_space (map);
103 isl_id *id = isl_space_get_tuple_id (d, isl_dim_in);
104
105 s = isl_set_set_tuple_id (s, id);
106 isl_space_free (d);
107 return isl_map_intersect_domain (map, s);
108 }
109
110 /* Constrain pdr->accesses with pdr->extent and pbb->domain. */
111
112 static isl_map *
113 add_pdr_constraints (poly_dr_p pdr, poly_bb_p pbb)
114 {
115 isl_map *x = isl_map_intersect_range (isl_map_copy (pdr->accesses),
116 isl_set_copy (pdr->extent));
117 x = constrain_domain (x, isl_set_copy (pbb->domain));
118 return x;
119 }
120
121 /* Returns all the memory reads in SCOP. */
122
123 static isl_union_map *
124 scop_get_reads (scop_p scop, vec<poly_bb_p> pbbs)
125 {
126 int i, j;
127 poly_bb_p pbb;
128 poly_dr_p pdr;
129 isl_space *space = isl_set_get_space (scop->context);
130 isl_union_map *res = isl_union_map_empty (space);
131
132 FOR_EACH_VEC_ELT (pbbs, i, pbb)
133 {
134 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
135 if (pdr_read_p (pdr))
136 res = isl_union_map_add_map (res, add_pdr_constraints (pdr, pbb));
137 }
138
139 return res;
140 }
141
142 /* Returns all the memory must writes in SCOP. */
143
144 static isl_union_map *
145 scop_get_must_writes (scop_p scop, vec<poly_bb_p> pbbs)
146 {
147 int i, j;
148 poly_bb_p pbb;
149 poly_dr_p pdr;
150 isl_space *space = isl_set_get_space (scop->context);
151 isl_union_map *res = isl_union_map_empty (space);
152
153 FOR_EACH_VEC_ELT (pbbs, i, pbb)
154 {
155 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
156 if (pdr_write_p (pdr))
157 res = isl_union_map_add_map (res, add_pdr_constraints (pdr, pbb));
158 }
159
160 return res;
161 }
162
163 /* Returns all the memory may writes in SCOP. */
164
165 static isl_union_map *
166 scop_get_may_writes (scop_p scop, vec<poly_bb_p> pbbs)
167 {
168 int i, j;
169 poly_bb_p pbb;
170 poly_dr_p pdr;
171 isl_space *space = isl_set_get_space (scop->context);
172 isl_union_map *res = isl_union_map_empty (space);
173
174 FOR_EACH_VEC_ELT (pbbs, i, pbb)
175 {
176 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
177 if (pdr_may_write_p (pdr))
178 res = isl_union_map_add_map (res, add_pdr_constraints (pdr, pbb));
179 }
180
181 return res;
182 }
183
184 /* Returns all the original schedules in SCOP. */
185
186 static isl_union_map *
187 scop_get_original_schedule (scop_p scop, vec<poly_bb_p> pbbs)
188 {
189 int i;
190 poly_bb_p pbb;
191 isl_space *space = isl_set_get_space (scop->context);
192 isl_union_map *res = isl_union_map_empty (space);
193
194 FOR_EACH_VEC_ELT (pbbs, i, pbb)
195 {
196 res = isl_union_map_add_map
197 (res, constrain_domain (isl_map_copy (pbb->schedule),
198 isl_set_copy (pbb->domain)));
199 }
200
201 return res;
202 }
203
204 /* Returns all the transformed schedules in SCOP. */
205
206 static isl_union_map *
207 scop_get_transformed_schedule (scop_p scop, vec<poly_bb_p> pbbs)
208 {
209 int i;
210 poly_bb_p pbb;
211 isl_space *space = isl_set_get_space (scop->context);
212 isl_union_map *res = isl_union_map_empty (space);
213
214 FOR_EACH_VEC_ELT (pbbs, i, pbb)
215 {
216 res = isl_union_map_add_map
217 (res, constrain_domain (isl_map_copy (pbb->transformed),
218 isl_set_copy (pbb->domain)));
219 }
220
221 return res;
222 }
223
224 /* Helper function used on each MAP of a isl_union_map. Computes the
225 maximal output dimension. */
226
227 static int
228 max_number_of_out_dimensions (__isl_take isl_map *map, void *user)
229 {
230 int global_max = *((int *) user);
231 isl_space *space = isl_map_get_space (map);
232 int nb_out = isl_space_dim (space, isl_dim_out);
233
234 if (global_max < nb_out)
235 *((int *) user) = nb_out;
236
237 isl_map_free (map);
238 isl_space_free (space);
239 return 0;
240 }
241
242 /* Extends the output dimension of MAP to MAX dimensions. */
243
244 static __isl_give isl_map *
245 extend_map (__isl_take isl_map *map, int max)
246 {
247 isl_space *space = isl_map_get_space (map);
248 int n = isl_space_dim (space, isl_dim_out);
249
250 isl_space_free (space);
251 return isl_map_add_dims (map, isl_dim_out, max - n);
252 }
253
254 /* Structure used to pass parameters to extend_schedule_1. */
255
256 struct extend_schedule_str {
257 int max;
258 isl_union_map *umap;
259 };
260
261 /* Helper function for extend_schedule. */
262
263 static int
264 extend_schedule_1 (__isl_take isl_map *map, void *user)
265 {
266 struct extend_schedule_str *str = (struct extend_schedule_str *) user;
267 str->umap = isl_union_map_add_map (str->umap, extend_map (map, str->max));
268 return 0;
269 }
270
271 /* Return a relation that has uniform output dimensions. */
272
273 __isl_give isl_union_map *
274 extend_schedule (__isl_take isl_union_map *x)
275 {
276 int max = 0;
277 int res;
278 struct extend_schedule_str str;
279
280 res = isl_union_map_foreach_map (x, max_number_of_out_dimensions, (void *) &max);
281 gcc_assert (res == 0);
282
283 str.max = max;
284 str.umap = isl_union_map_empty (isl_union_map_get_space (x));
285 res = isl_union_map_foreach_map (x, extend_schedule_1, (void *) &str);
286 gcc_assert (res == 0);
287
288 isl_union_map_free (x);
289 return str.umap;
290 }
291
292 /* Applies SCHEDULE to the in and out dimensions of the dependences
293 DEPS and return the resulting relation. */
294
295 static isl_map *
296 apply_schedule_on_deps (__isl_keep isl_union_map *schedule,
297 __isl_keep isl_union_map *deps)
298 {
299 isl_map *x;
300 isl_union_map *ux, *trans;
301
302 trans = isl_union_map_copy (schedule);
303 trans = extend_schedule (trans);
304 ux = isl_union_map_copy (deps);
305 ux = isl_union_map_apply_domain (ux, isl_union_map_copy (trans));
306 ux = isl_union_map_apply_range (ux, trans);
307 if (isl_union_map_is_empty (ux))
308 {
309 isl_union_map_free (ux);
310 return NULL;
311 }
312 x = isl_map_from_union_map (ux);
313
314 return x;
315 }
316
317 /* Return true when SCHEDULE does not violate the data DEPS: that is
318 when the intersection of LEX with the DEPS transformed by SCHEDULE
319 is empty. LEX is the relation in which the outputs occur before
320 the inputs. */
321
322 static bool
323 no_violations (__isl_keep isl_union_map *schedule,
324 __isl_keep isl_union_map *deps)
325 {
326 bool res;
327 isl_space *space;
328 isl_map *lex, *x;
329
330 if (isl_union_map_is_empty (deps))
331 return true;
332
333 x = apply_schedule_on_deps (schedule, deps);
334 space = isl_map_get_space (x);
335 space = isl_space_range (space);
336 lex = isl_map_lex_ge (space);
337 x = isl_map_intersect (x, lex);
338 res = isl_map_is_empty (x);
339
340 isl_map_free (x);
341 return res;
342 }
343
344 /* Return true when DEPS is non empty and the intersection of LEX with
345 the DEPS transformed by SCHEDULE is non empty. LEX is the relation
346 in which all the inputs before DEPTH occur at the same time as the
347 output, and the input at DEPTH occurs before output. */
348
349 bool
350 carries_deps (__isl_keep isl_union_map *schedule,
351 __isl_keep isl_union_map *deps,
352 int depth)
353 {
354 bool res;
355 int i;
356 isl_space *space;
357 isl_map *lex, *x;
358 isl_constraint *ineq;
359
360 if (isl_union_map_is_empty (deps))
361 return false;
362
363 x = apply_schedule_on_deps (schedule, deps);
364 if (x == NULL)
365 return false;
366 space = isl_map_get_space (x);
367 space = isl_space_range (space);
368 lex = isl_map_lex_le (space);
369 space = isl_map_get_space (x);
370 ineq = isl_inequality_alloc (isl_local_space_from_space (space));
371
372 for (i = 0; i < depth - 1; i++)
373 lex = isl_map_equate (lex, isl_dim_in, i, isl_dim_out, i);
374
375 /* in + 1 <= out */
376 ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_out, depth - 1, 1);
377 ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_in, depth - 1, -1);
378 ineq = isl_constraint_set_constant_si (ineq, -1);
379 lex = isl_map_add_constraint (lex, ineq);
380 x = isl_map_intersect (x, lex);
381 res = !isl_map_is_empty (x);
382
383 isl_map_free (x);
384 return res;
385 }
386
387 /* Subtract from the RAW, WAR, and WAW dependences those relations
388 that have been marked as belonging to an associative commutative
389 reduction. */
390
391 static void
392 subtract_commutative_associative_deps (scop_p scop,
393 vec<poly_bb_p> pbbs,
394 isl_union_map *original,
395 isl_union_map **must_raw,
396 isl_union_map **may_raw,
397 isl_union_map **must_raw_no_source,
398 isl_union_map **may_raw_no_source,
399 isl_union_map **must_war,
400 isl_union_map **may_war,
401 isl_union_map **must_war_no_source,
402 isl_union_map **may_war_no_source,
403 isl_union_map **must_waw,
404 isl_union_map **may_waw,
405 isl_union_map **must_waw_no_source,
406 isl_union_map **may_waw_no_source)
407 {
408 int i, j;
409 poly_bb_p pbb;
410 poly_dr_p pdr;
411 isl_space *space = isl_set_get_space (scop->context);
412
413 FOR_EACH_VEC_ELT (pbbs, i, pbb)
414 if (PBB_IS_REDUCTION (pbb))
415 {
416 int res;
417 isl_union_map *r = isl_union_map_empty (isl_space_copy (space));
418 isl_union_map *must_w = isl_union_map_empty (isl_space_copy (space));
419 isl_union_map *may_w = isl_union_map_empty (isl_space_copy (space));
420 isl_union_map *all_w;
421 isl_union_map *empty;
422 isl_union_map *x_must_raw;
423 isl_union_map *x_may_raw;
424 isl_union_map *x_must_raw_no_source;
425 isl_union_map *x_may_raw_no_source;
426 isl_union_map *x_must_war;
427 isl_union_map *x_may_war;
428 isl_union_map *x_must_war_no_source;
429 isl_union_map *x_may_war_no_source;
430 isl_union_map *x_must_waw;
431 isl_union_map *x_may_waw;
432 isl_union_map *x_must_waw_no_source;
433 isl_union_map *x_may_waw_no_source;
434
435 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
436 if (pdr_read_p (pdr))
437 r = isl_union_map_add_map (r, add_pdr_constraints (pdr, pbb));
438
439 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
440 if (pdr_write_p (pdr))
441 must_w = isl_union_map_add_map (must_w,
442 add_pdr_constraints (pdr, pbb));
443
444 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr)
445 if (pdr_may_write_p (pdr))
446 may_w = isl_union_map_add_map (may_w,
447 add_pdr_constraints (pdr, pbb));
448
449 all_w = isl_union_map_union
450 (isl_union_map_copy (must_w), isl_union_map_copy (may_w));
451 empty = isl_union_map_empty (isl_union_map_get_space (all_w));
452
453 res = isl_union_map_compute_flow (isl_union_map_copy (r),
454 isl_union_map_copy (must_w),
455 isl_union_map_copy (may_w),
456 isl_union_map_copy (original),
457 &x_must_raw, &x_may_raw,
458 &x_must_raw_no_source,
459 &x_may_raw_no_source);
460 gcc_assert (res == 0);
461 res = isl_union_map_compute_flow (isl_union_map_copy (all_w),
462 r, empty,
463 isl_union_map_copy (original),
464 &x_must_war, &x_may_war,
465 &x_must_war_no_source,
466 &x_may_war_no_source);
467 gcc_assert (res == 0);
468 res = isl_union_map_compute_flow (all_w, must_w, may_w,
469 isl_union_map_copy (original),
470 &x_must_waw, &x_may_waw,
471 &x_must_waw_no_source,
472 &x_may_waw_no_source);
473 gcc_assert (res == 0);
474
475 if (must_raw)
476 *must_raw = isl_union_map_subtract (*must_raw, x_must_raw);
477 else
478 isl_union_map_free (x_must_raw);
479
480 if (may_raw)
481 *may_raw = isl_union_map_subtract (*may_raw, x_may_raw);
482 else
483 isl_union_map_free (x_may_raw);
484
485 if (must_raw_no_source)
486 *must_raw_no_source = isl_union_map_subtract (*must_raw_no_source,
487 x_must_raw_no_source);
488 else
489 isl_union_map_free (x_must_raw_no_source);
490
491 if (may_raw_no_source)
492 *may_raw_no_source = isl_union_map_subtract (*may_raw_no_source,
493 x_may_raw_no_source);
494 else
495 isl_union_map_free (x_may_raw_no_source);
496
497 if (must_war)
498 *must_war = isl_union_map_subtract (*must_war, x_must_war);
499 else
500 isl_union_map_free (x_must_war);
501
502 if (may_war)
503 *may_war = isl_union_map_subtract (*may_war, x_may_war);
504 else
505 isl_union_map_free (x_may_war);
506
507 if (must_war_no_source)
508 *must_war_no_source = isl_union_map_subtract (*must_war_no_source,
509 x_must_war_no_source);
510 else
511 isl_union_map_free (x_must_war_no_source);
512
513 if (may_war_no_source)
514 *may_war_no_source = isl_union_map_subtract (*may_war_no_source,
515 x_may_war_no_source);
516 else
517 isl_union_map_free (x_may_war_no_source);
518
519 if (must_waw)
520 *must_waw = isl_union_map_subtract (*must_waw, x_must_waw);
521 else
522 isl_union_map_free (x_must_waw);
523
524 if (may_waw)
525 *may_waw = isl_union_map_subtract (*may_waw, x_may_waw);
526 else
527 isl_union_map_free (x_may_waw);
528
529 if (must_waw_no_source)
530 *must_waw_no_source = isl_union_map_subtract (*must_waw_no_source,
531 x_must_waw_no_source);
532 else
533 isl_union_map_free (x_must_waw_no_source);
534
535 if (may_waw_no_source)
536 *may_waw_no_source = isl_union_map_subtract (*may_waw_no_source,
537 x_may_waw_no_source);
538 else
539 isl_union_map_free (x_may_waw_no_source);
540 }
541
542 isl_union_map_free (original);
543 isl_space_free (space);
544 }
545
546 /* Compute the original data dependences in SCOP for all the reads and
547 writes in PBBS. */
548
549 void
550 compute_deps (scop_p scop, vec<poly_bb_p> pbbs,
551 isl_union_map **must_raw,
552 isl_union_map **may_raw,
553 isl_union_map **must_raw_no_source,
554 isl_union_map **may_raw_no_source,
555 isl_union_map **must_war,
556 isl_union_map **may_war,
557 isl_union_map **must_war_no_source,
558 isl_union_map **may_war_no_source,
559 isl_union_map **must_waw,
560 isl_union_map **may_waw,
561 isl_union_map **must_waw_no_source,
562 isl_union_map **may_waw_no_source)
563 {
564 isl_union_map *reads = scop_get_reads (scop, pbbs);
565 isl_union_map *must_writes = scop_get_must_writes (scop, pbbs);
566 isl_union_map *may_writes = scop_get_may_writes (scop, pbbs);
567 isl_union_map *all_writes = isl_union_map_union
568 (isl_union_map_copy (must_writes), isl_union_map_copy (may_writes));
569 isl_space *space = isl_union_map_get_space (all_writes);
570 isl_union_map *empty = isl_union_map_empty (space);
571 isl_union_map *original = scop_get_original_schedule (scop, pbbs);
572 int res;
573
574 res = isl_union_map_compute_flow (isl_union_map_copy (reads),
575 isl_union_map_copy (must_writes),
576 isl_union_map_copy (may_writes),
577 isl_union_map_copy (original),
578 must_raw, may_raw, must_raw_no_source,
579 may_raw_no_source);
580 gcc_assert (res == 0);
581 res = isl_union_map_compute_flow (isl_union_map_copy (all_writes),
582 reads, empty,
583 isl_union_map_copy (original),
584 must_war, may_war, must_war_no_source,
585 may_war_no_source);
586 gcc_assert (res == 0);
587 res = isl_union_map_compute_flow (all_writes, must_writes, may_writes,
588 isl_union_map_copy (original),
589 must_waw, may_waw, must_waw_no_source,
590 may_waw_no_source);
591 gcc_assert (res == 0);
592
593 subtract_commutative_associative_deps
594 (scop, pbbs, original,
595 must_raw, may_raw, must_raw_no_source, may_raw_no_source,
596 must_war, may_war, must_war_no_source, may_war_no_source,
597 must_waw, may_waw, must_waw_no_source, may_waw_no_source);
598 }
599
600 /* Given a TRANSFORM, check whether it respects the original
601 dependences in SCOP. Returns true when TRANSFORM is a safe
602 transformation. */
603
604 static bool
605 transform_is_safe (scop_p scop, isl_union_map *transform)
606 {
607 bool res;
608
609 if (!scop->must_raw)
610 compute_deps (scop, SCOP_BBS (scop),
611 &scop->must_raw, &scop->may_raw,
612 &scop->must_raw_no_source, &scop->may_raw_no_source,
613 &scop->must_war, &scop->may_war,
614 &scop->must_war_no_source, &scop->may_war_no_source,
615 &scop->must_waw, &scop->may_waw,
616 &scop->must_waw_no_source, &scop->may_waw_no_source);
617
618 res = (no_violations (transform, scop->must_raw)
619 && no_violations (transform, scop->may_raw)
620 && no_violations (transform, scop->must_war)
621 && no_violations (transform, scop->may_war)
622 && no_violations (transform, scop->must_waw)
623 && no_violations (transform, scop->may_waw));
624
625 isl_union_map_free (transform);
626 return res;
627 }
628
629 /* Return true when the SCOP transformed schedule is correct. */
630
631 bool
632 graphite_legal_transform (scop_p scop)
633 {
634 int res;
635 isl_union_map *transform;
636
637 timevar_push (TV_GRAPHITE_DATA_DEPS);
638 transform = scop_get_transformed_schedule (scop, SCOP_BBS (scop));
639 res = transform_is_safe (scop, transform);
640 timevar_pop (TV_GRAPHITE_DATA_DEPS);
641
642 return res;
643 }
644
645 #endif