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