libstdc++: Simplify std::any to fix -Wdeprecated-declarations warning
[official-gcc.git] / gcc / graphite-dependences.cc
blob41e1114173bfd259ca3c4cec267d3d5ccbf96b7a
1 /* Data dependence analysis for Graphite.
2 Copyright (C) 2009-2024 Free Software Foundation, Inc.
3 Contributed by Sebastian Pop <sebastian.pop@amd.com> and
4 Konrad Trifunovic <konrad.trifunovic@inria.fr>.
6 This file is part of GCC.
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.
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.
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/>. */
22 #define INCLUDE_ISL
23 #define INCLUDE_MEMORY
25 #include "config.h"
27 #ifdef HAVE_isl
29 #include "system.h"
30 #include "coretypes.h"
31 #include "backend.h"
32 #include "cfghooks.h"
33 #include "tree.h"
34 #include "gimple.h"
35 #include "fold-const.h"
36 #include "gimple-iterator.h"
37 #include "tree-ssa-loop.h"
38 #include "tree-pass.h"
39 #include "cfgloop.h"
40 #include "tree-data-ref.h"
41 #include "graphite.h"
43 /* Add the constraints from the set S to the domain of MAP. */
45 static isl_map *
46 constrain_domain (isl_map *map, isl_set *s)
48 isl_space *d = isl_map_get_space (map);
49 isl_id *id = isl_space_get_tuple_id (d, isl_dim_in);
51 s = isl_set_set_tuple_id (s, id);
52 isl_space_free (d);
53 return isl_map_coalesce (isl_map_intersect_domain (map, s));
56 /* Constrain pdr->accesses with pdr->subscript_sizes and pbb->domain. */
58 static isl_map *
59 add_pdr_constraints (poly_dr_p pdr, poly_bb_p pbb)
61 isl_map *x = isl_map_intersect_range (isl_map_copy (pdr->accesses),
62 isl_set_copy (pdr->subscript_sizes));
63 x = isl_map_coalesce (x);
64 return constrain_domain (x, isl_set_copy (pbb->domain));
67 /* Returns an isl description of all memory operations in SCOP. The memory
68 reads are returned in READS and writes in MUST_WRITES and MAY_WRITES. */
70 static void
71 scop_get_reads_and_writes (scop_p scop, isl_union_map *&reads,
72 isl_union_map *&must_writes,
73 isl_union_map *&may_writes)
75 int i, j;
76 poly_bb_p pbb;
77 poly_dr_p pdr;
79 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
81 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr) {
82 if (pdr_read_p (pdr))
84 if (dump_file)
86 fprintf (dump_file, "Adding read to depedence graph: ");
87 print_pdr (dump_file, pdr);
89 isl_union_map *um
90 = isl_union_map_from_map (add_pdr_constraints (pdr, pbb));
91 reads = isl_union_map_union (reads, um);
92 if (dump_file)
94 fprintf (dump_file, "Reads depedence graph: ");
95 print_isl_union_map (dump_file, reads);
98 else if (pdr_write_p (pdr))
100 if (dump_file)
102 fprintf (dump_file, "Adding must write to depedence graph: ");
103 print_pdr (dump_file, pdr);
105 isl_union_map *um
106 = isl_union_map_from_map (add_pdr_constraints (pdr, pbb));
107 must_writes = isl_union_map_union (must_writes, um);
108 if (dump_file)
110 fprintf (dump_file, "Must writes depedence graph: ");
111 print_isl_union_map (dump_file, must_writes);
114 else if (pdr_may_write_p (pdr))
116 if (dump_file)
118 fprintf (dump_file, "Adding may write to depedence graph: ");
119 print_pdr (dump_file, pdr);
121 isl_union_map *um
122 = isl_union_map_from_map (add_pdr_constraints (pdr, pbb));
123 may_writes = isl_union_map_union (may_writes, um);
124 if (dump_file)
126 fprintf (dump_file, "May writes depedence graph: ");
127 print_isl_union_map (dump_file, may_writes);
134 /* Helper function used on each MAP of a isl_union_map. Computes the
135 maximal output dimension. */
137 static isl_stat
138 max_number_of_out_dimensions (__isl_take isl_map *map, void *user)
140 int global_max = *((int *) user);
141 isl_space *space = isl_map_get_space (map);
142 int nb_out = isl_space_dim (space, isl_dim_out);
144 if (global_max < nb_out)
145 *((int *) user) = nb_out;
147 isl_map_free (map);
148 isl_space_free (space);
149 return isl_stat_ok;
152 /* Extends the output dimension of MAP to MAX dimensions. */
154 static __isl_give isl_map *
155 extend_map (__isl_take isl_map *map, int max)
157 isl_space *space = isl_map_get_space (map);
158 int n = isl_space_dim (space, isl_dim_out);
160 isl_space_free (space);
161 return isl_map_add_dims (map, isl_dim_out, max - n);
164 /* Structure used to pass parameters to extend_schedule_1. */
166 struct extend_schedule_str {
167 int max;
168 isl_union_map *umap;
171 /* Helper function for extend_schedule. */
173 static isl_stat
174 extend_schedule_1 (__isl_take isl_map *map, void *user)
176 struct extend_schedule_str *str = (struct extend_schedule_str *) user;
177 str->umap = isl_union_map_add_map (str->umap, extend_map (map, str->max));
178 return isl_stat_ok;
181 /* Return a relation that has uniform output dimensions. */
183 static __isl_give isl_union_map *
184 extend_schedule (__isl_take isl_union_map *x)
186 int max = 0;
187 struct extend_schedule_str str;
189 isl_union_map_foreach_map (x, max_number_of_out_dimensions, (void *) &max);
190 str.max = max;
191 str.umap = isl_union_map_empty (isl_union_map_get_space (x));
192 isl_union_map_foreach_map (x, extend_schedule_1, (void *) &str);
193 isl_union_map_free (x);
194 return isl_union_map_coalesce (str.umap);
197 /* Applies SCHEDULE to the in and out dimensions of the dependences
198 DEPS and return the resulting relation. */
200 static isl_map *
201 apply_schedule_on_deps (__isl_keep isl_union_map *schedule,
202 __isl_keep isl_union_map *deps)
204 isl_union_map *trans = extend_schedule (isl_union_map_copy (schedule));
205 isl_union_map *ux = isl_union_map_copy (deps);
206 ux = isl_union_map_apply_domain (ux, isl_union_map_copy (trans));
207 ux = isl_union_map_apply_range (ux, trans);
208 ux = isl_union_map_coalesce (ux);
210 if (!isl_union_map_is_empty (ux))
211 return isl_map_from_union_map (ux);
213 isl_union_map_free (ux);
214 return NULL;
217 /* Return true when DEPS is non empty and the intersection of LEX with
218 the DEPS transformed by SCHEDULE is non empty. LEX is the relation
219 in which all the inputs before DEPTH occur at the same time as the
220 output, and the input at DEPTH occurs before output. */
222 bool
223 carries_deps (__isl_keep isl_union_map *schedule,
224 __isl_keep isl_union_map *deps,
225 int depth)
227 if (isl_union_map_is_empty (deps))
228 return false;
230 isl_map *x = apply_schedule_on_deps (schedule, deps);
231 if (x == NULL)
232 return false;
234 isl_space *space = isl_map_get_space (x);
235 isl_map *lex = isl_map_lex_le (isl_space_range (space));
236 isl_constraint *ineq = isl_inequality_alloc
237 (isl_local_space_from_space (isl_map_get_space (x)));
239 for (int i = 0; i < depth - 1; i++)
240 lex = isl_map_equate (lex, isl_dim_in, i, isl_dim_out, i);
242 /* in + 1 <= out */
243 ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_out, depth - 1, 1);
244 ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_in, depth - 1, -1);
245 ineq = isl_constraint_set_constant_si (ineq, -1);
246 lex = isl_map_add_constraint (lex, ineq);
247 lex = isl_map_coalesce (lex);
248 x = isl_map_intersect (x, lex);
249 bool res = !isl_map_is_empty (x);
251 isl_map_free (x);
252 return res;
255 /* Compute the dependence relations for the SCOP:
256 RAW are read after write dependences,
257 WAR are write after read dependences,
258 WAW are write after write dependences. */
260 void
261 scop_get_dependences (scop_p scop)
263 if (scop->dependence)
264 return;
266 isl_space *space = isl_set_get_space (scop->param_context);
267 isl_union_map *reads = isl_union_map_empty (isl_space_copy (space));
268 isl_union_map *must_writes = isl_union_map_empty (isl_space_copy (space));
269 isl_union_map *may_writes = isl_union_map_empty (space);
270 scop_get_reads_and_writes (scop, reads, must_writes, may_writes);
272 if (dump_file)
274 fprintf (dump_file, "\n--- Documentation for datarefs dump: ---\n");
275 fprintf (dump_file, "Statements on the iteration domain are mapped to"
276 " array references.\n");
277 fprintf (dump_file, " To read the following data references:\n\n");
278 fprintf (dump_file, " S_5[i0] -> [106] : i0 >= 0 and i0 <= 3\n");
279 fprintf (dump_file, " S_8[i0] -> [1, i0] : i0 >= 0 and i0 <= 3\n\n");
281 fprintf (dump_file, " S_5[i0] is the dynamic instance of statement"
282 " bb_5 in a loop that accesses all iterations 0 <= i0 <= 3.\n");
283 fprintf (dump_file, " [1, i0] is a 'memref' with alias set 1"
284 " and first subscript access i0.\n");
285 fprintf (dump_file, " [106] is a 'scalar reference' which is the sum of"
286 " SSA_NAME_VERSION 6"
287 " and --param graphite-max-arrays-per-scop=100\n");
288 fprintf (dump_file, "-----------------------\n\n");
290 fprintf (dump_file, "data references (\n");
291 fprintf (dump_file, " reads: ");
292 print_isl_union_map (dump_file, reads);
293 fprintf (dump_file, " must_writes: ");
294 print_isl_union_map (dump_file, must_writes);
295 fprintf (dump_file, " may_writes: ");
296 print_isl_union_map (dump_file, may_writes);
297 fprintf (dump_file, ")\n");
300 gcc_assert (scop->original_schedule);
302 isl_union_access_info *ai;
303 ai = isl_union_access_info_from_sink (isl_union_map_copy (reads));
304 ai = isl_union_access_info_set_must_source (ai, isl_union_map_copy (must_writes));
305 ai = isl_union_access_info_set_may_source (ai, may_writes);
306 ai = isl_union_access_info_set_schedule
307 (ai, isl_schedule_copy (scop->original_schedule));
308 isl_union_flow *flow = isl_union_access_info_compute_flow (ai);
309 isl_union_map *raw = isl_union_flow_get_must_dependence (flow);
310 isl_union_flow_free (flow);
312 ai = isl_union_access_info_from_sink (isl_union_map_copy (must_writes));
313 ai = isl_union_access_info_set_must_source (ai, must_writes);
314 ai = isl_union_access_info_set_may_source (ai, reads);
315 ai = isl_union_access_info_set_schedule
316 (ai, isl_schedule_copy (scop->original_schedule));
317 flow = isl_union_access_info_compute_flow (ai);
319 isl_union_map *waw = isl_union_flow_get_must_dependence (flow);
320 isl_union_map *war = isl_union_flow_get_may_dependence (flow);
321 war = isl_union_map_subtract (war, isl_union_map_copy (waw));
322 isl_union_flow_free (flow);
324 raw = isl_union_map_coalesce (raw);
325 waw = isl_union_map_coalesce (waw);
326 war = isl_union_map_coalesce (war);
328 isl_union_map *dependences = raw;
329 dependences = isl_union_map_union (dependences, war);
330 dependences = isl_union_map_union (dependences, waw);
331 dependences = isl_union_map_coalesce (dependences);
333 if (dump_file)
335 fprintf (dump_file, "data dependences (\n");
336 print_isl_union_map (dump_file, dependences);
337 fprintf (dump_file, ")\n");
340 scop->dependence = dependences;
343 #endif /* HAVE_isl */