]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/graphite-dependences.c
Put the CL into the right dir.
[thirdparty/gcc.git] / gcc / graphite-dependences.c
CommitLineData
c6bb733d 1/* Data dependence analysis for Graphite.
fbd26352 2 Copyright (C) 2009-2019 Free Software Foundation, Inc.
c6bb733d 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
d8a2c81e 22#define USES_ISL
23
c6bb733d 24#include "config.h"
87e20041 25
429cca51 26#ifdef HAVE_isl
87e20041 27
c6bb733d 28#include "system.h"
29#include "coretypes.h"
9ef16211 30#include "backend.h"
d040a5b0 31#include "cfghooks.h"
b20a8bb4 32#include "tree.h"
9ef16211 33#include "gimple.h"
9ef16211 34#include "fold-const.h"
dcf1a1ec 35#include "gimple-iterator.h"
073c1fd5 36#include "tree-ssa-loop.h"
f0a18dd2 37#include "tree-pass.h"
c6bb733d 38#include "cfgloop.h"
c6bb733d 39#include "tree-data-ref.h"
39b8c5f3 40#include "graphite.h"
0d6b5db2 41
87e20041 42/* Add the constraints from the set S to the domain of MAP. */
c6bb733d 43
87e20041 44static isl_map *
45constrain_domain (isl_map *map, isl_set *s)
0d6b5db2 46{
87e20041 47 isl_space *d = isl_map_get_space (map);
48 isl_id *id = isl_space_get_tuple_id (d, isl_dim_in);
a071b80b 49
87e20041 50 s = isl_set_set_tuple_id (s, id);
51 isl_space_free (d);
ece4d5b1 52 return isl_map_coalesce (isl_map_intersect_domain (map, s));
a071b80b 53}
54
fc25c670 55/* Constrain pdr->accesses with pdr->subscript_sizes and pbb->domain. */
a071b80b 56
87e20041 57static isl_map *
58add_pdr_constraints (poly_dr_p pdr, poly_bb_p pbb)
a071b80b 59{
87e20041 60 isl_map *x = isl_map_intersect_range (isl_map_copy (pdr->accesses),
fc25c670 61 isl_set_copy (pdr->subscript_sizes));
ece4d5b1 62 x = isl_map_coalesce (x);
63 return constrain_domain (x, isl_set_copy (pbb->domain));
a071b80b 64}
65
9c61da99 66/* Returns an isl description of all memory operations in SCOP. The memory
67 reads are returned in READS and writes in MUST_WRITES and MAY_WRITES. */
a071b80b 68
9c61da99 69static void
4a052765 70scop_get_reads_and_writes (scop_p scop, isl_union_map *&reads,
71 isl_union_map *&must_writes,
72 isl_union_map *&may_writes)
a071b80b 73{
87e20041 74 int i, j;
75 poly_bb_p pbb;
76 poly_dr_p pdr;
a071b80b 77
c1616982 78 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
0d6b5db2 79 {
9c61da99 80 FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr) {
87e20041 81 if (pdr_read_p (pdr))
fead8d0e 82 {
83 if (dump_file)
6fb10557 84 {
85 fprintf (dump_file, "Adding read to depedence graph: ");
86 print_pdr (dump_file, pdr);
87 }
c1616982 88 isl_union_map *um
89 = isl_union_map_from_map (add_pdr_constraints (pdr, pbb));
9c61da99 90 reads = isl_union_map_union (reads, um);
6fb10557 91 if (dump_file)
92 {
93 fprintf (dump_file, "Reads depedence graph: ");
9c61da99 94 print_isl_union_map (dump_file, reads);
6fb10557 95 }
fead8d0e 96 }
9c61da99 97 else if (pdr_write_p (pdr))
fead8d0e 98 {
99 if (dump_file)
6fb10557 100 {
101 fprintf (dump_file, "Adding must write to depedence graph: ");
102 print_pdr (dump_file, pdr);
103 }
c1616982 104 isl_union_map *um
105 = isl_union_map_from_map (add_pdr_constraints (pdr, pbb));
9c61da99 106 must_writes = isl_union_map_union (must_writes, um);
6fb10557 107 if (dump_file)
108 {
109 fprintf (dump_file, "Must writes depedence graph: ");
9c61da99 110 print_isl_union_map (dump_file, must_writes);
6fb10557 111 }
fead8d0e 112 }
9c61da99 113 else if (pdr_may_write_p (pdr))
fead8d0e 114 {
115 if (dump_file)
6fb10557 116 {
117 fprintf (dump_file, "Adding may write to depedence graph: ");
118 print_pdr (dump_file, pdr);
119 }
c1616982 120 isl_union_map *um
121 = isl_union_map_from_map (add_pdr_constraints (pdr, pbb));
9c61da99 122 may_writes = isl_union_map_union (may_writes, um);
6fb10557 123 if (dump_file)
124 {
125 fprintf (dump_file, "May writes depedence graph: ");
9c61da99 126 print_isl_union_map (dump_file, may_writes);
6fb10557 127 }
fead8d0e 128 }
9c61da99 129 }
abc97125 130 }
c6bb733d 131}
132
87e20041 133/* Helper function used on each MAP of a isl_union_map. Computes the
134 maximal output dimension. */
f007fe97 135
a26dad6a 136static isl_stat
87e20041 137max_number_of_out_dimensions (__isl_take isl_map *map, void *user)
f007fe97 138{
87e20041 139 int global_max = *((int *) user);
140 isl_space *space = isl_map_get_space (map);
141 int nb_out = isl_space_dim (space, isl_dim_out);
f007fe97 142
87e20041 143 if (global_max < nb_out)
144 *((int *) user) = nb_out;
f007fe97 145
87e20041 146 isl_map_free (map);
147 isl_space_free (space);
a26dad6a 148 return isl_stat_ok;
f007fe97 149}
150
87e20041 151/* Extends the output dimension of MAP to MAX dimensions. */
f007fe97 152
87e20041 153static __isl_give isl_map *
154extend_map (__isl_take isl_map *map, int max)
f007fe97 155{
87e20041 156 isl_space *space = isl_map_get_space (map);
157 int n = isl_space_dim (space, isl_dim_out);
a071b80b 158
87e20041 159 isl_space_free (space);
160 return isl_map_add_dims (map, isl_dim_out, max - n);
f007fe97 161}
162
87e20041 163/* Structure used to pass parameters to extend_schedule_1. */
0d6b5db2 164
87e20041 165struct extend_schedule_str {
166 int max;
167 isl_union_map *umap;
168};
c6bb733d 169
87e20041 170/* Helper function for extend_schedule. */
30f4f4a6 171
a26dad6a 172static isl_stat
87e20041 173extend_schedule_1 (__isl_take isl_map *map, void *user)
30f4f4a6 174{
87e20041 175 struct extend_schedule_str *str = (struct extend_schedule_str *) user;
176 str->umap = isl_union_map_add_map (str->umap, extend_map (map, str->max));
a26dad6a 177 return isl_stat_ok;
30f4f4a6 178}
179
87e20041 180/* Return a relation that has uniform output dimensions. */
c6bb733d 181
7a833a09 182static __isl_give isl_union_map *
87e20041 183extend_schedule (__isl_take isl_union_map *x)
c6bb733d 184{
87e20041 185 int max = 0;
87e20041 186 struct extend_schedule_str str;
c6bb733d 187
36620673 188 isl_union_map_foreach_map (x, max_number_of_out_dimensions, (void *) &max);
87e20041 189 str.max = max;
190 str.umap = isl_union_map_empty (isl_union_map_get_space (x));
36620673 191 isl_union_map_foreach_map (x, extend_schedule_1, (void *) &str);
87e20041 192 isl_union_map_free (x);
ece4d5b1 193 return isl_union_map_coalesce (str.umap);
c6bb733d 194}
195
87e20041 196/* Applies SCHEDULE to the in and out dimensions of the dependences
197 DEPS and return the resulting relation. */
c6bb733d 198
87e20041 199static isl_map *
200apply_schedule_on_deps (__isl_keep isl_union_map *schedule,
201 __isl_keep isl_union_map *deps)
c6bb733d 202{
ece4d5b1 203 isl_union_map *trans = extend_schedule (isl_union_map_copy (schedule));
204 isl_union_map *ux = isl_union_map_copy (deps);
87e20041 205 ux = isl_union_map_apply_domain (ux, isl_union_map_copy (trans));
206 ux = isl_union_map_apply_range (ux, trans);
ece4d5b1 207 ux = isl_union_map_coalesce (ux);
208
209 if (!isl_union_map_is_empty (ux))
210 return isl_map_from_union_map (ux);
c6bb733d 211
ece4d5b1 212 isl_union_map_free (ux);
213 return NULL;
c6bb733d 214}
215
87e20041 216/* Return true when DEPS is non empty and the intersection of LEX with
217 the DEPS transformed by SCHEDULE is non empty. LEX is the relation
218 in which all the inputs before DEPTH occur at the same time as the
219 output, and the input at DEPTH occurs before output. */
c6bb733d 220
86e09dcd 221bool
87e20041 222carries_deps (__isl_keep isl_union_map *schedule,
223 __isl_keep isl_union_map *deps,
224 int depth)
c6bb733d 225{
87e20041 226 if (isl_union_map_is_empty (deps))
227 return false;
c6bb733d 228
ece4d5b1 229 isl_map *x = apply_schedule_on_deps (schedule, deps);
86e09dcd 230 if (x == NULL)
231 return false;
87e20041 232
ece4d5b1 233 isl_space *space = isl_map_get_space (x);
234 isl_map *lex = isl_map_lex_le (isl_space_range (space));
235 isl_constraint *ineq = isl_inequality_alloc
236 (isl_local_space_from_space (isl_map_get_space (x)));
237
238 for (int i = 0; i < depth - 1; i++)
87e20041 239 lex = isl_map_equate (lex, isl_dim_in, i, isl_dim_out, i);
240
241 /* in + 1 <= out */
bffcae34 242 ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_out, depth - 1, 1);
243 ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_in, depth - 1, -1);
87e20041 244 ineq = isl_constraint_set_constant_si (ineq, -1);
245 lex = isl_map_add_constraint (lex, ineq);
ece4d5b1 246 lex = isl_map_coalesce (lex);
87e20041 247 x = isl_map_intersect (x, lex);
ece4d5b1 248 bool res = !isl_map_is_empty (x);
87e20041 249
250 isl_map_free (x);
251 return res;
c6bb733d 252}
253
c1616982 254/* Compute the dependence relations for the SCOP:
255 RAW are read after write dependences,
256 WAR are write after read dependences,
257 WAW are write after write dependences. */
258
259void
260scop_get_dependences (scop_p scop)
261{
262 if (scop->dependence)
263 return;
264
9c61da99 265 isl_space *space = isl_set_get_space (scop->param_context);
266 isl_union_map *reads = isl_union_map_empty (isl_space_copy (space));
267 isl_union_map *must_writes = isl_union_map_empty (isl_space_copy (space));
268 isl_union_map *may_writes = isl_union_map_empty (space);
269 scop_get_reads_and_writes (scop, reads, must_writes, may_writes);
c1616982 270
271 if (dump_file)
272 {
273 fprintf (dump_file, "\n--- Documentation for datarefs dump: ---\n");
274 fprintf (dump_file, "Statements on the iteration domain are mapped to"
275 " array references.\n");
276 fprintf (dump_file, " To read the following data references:\n\n");
277 fprintf (dump_file, " S_5[i0] -> [106] : i0 >= 0 and i0 <= 3\n");
278 fprintf (dump_file, " S_8[i0] -> [1, i0] : i0 >= 0 and i0 <= 3\n\n");
279
280 fprintf (dump_file, " S_5[i0] is the dynamic instance of statement"
281 " bb_5 in a loop that accesses all iterations 0 <= i0 <= 3.\n");
282 fprintf (dump_file, " [1, i0] is a 'memref' with alias set 1"
283 " and first subscript access i0.\n");
284 fprintf (dump_file, " [106] is a 'scalar reference' which is the sum of"
285 " SSA_NAME_VERSION 6"
286 " and --param graphite-max-arrays-per-scop=100\n");
287 fprintf (dump_file, "-----------------------\n\n");
288
289 fprintf (dump_file, "data references (\n");
290 fprintf (dump_file, " reads: ");
291 print_isl_union_map (dump_file, reads);
292 fprintf (dump_file, " must_writes: ");
293 print_isl_union_map (dump_file, must_writes);
294 fprintf (dump_file, " may_writes: ");
295 print_isl_union_map (dump_file, may_writes);
296 fprintf (dump_file, ")\n");
297 }
298
299 gcc_assert (scop->original_schedule);
300
301 isl_union_access_info *ai;
302 ai = isl_union_access_info_from_sink (isl_union_map_copy (reads));
303 ai = isl_union_access_info_set_must_source (ai, isl_union_map_copy (must_writes));
304 ai = isl_union_access_info_set_may_source (ai, may_writes);
305 ai = isl_union_access_info_set_schedule
306 (ai, isl_schedule_copy (scop->original_schedule));
307 isl_union_flow *flow = isl_union_access_info_compute_flow (ai);
308 isl_union_map *raw = isl_union_flow_get_must_dependence (flow);
309 isl_union_flow_free (flow);
310
311 ai = isl_union_access_info_from_sink (isl_union_map_copy (must_writes));
312 ai = isl_union_access_info_set_must_source (ai, must_writes);
313 ai = isl_union_access_info_set_may_source (ai, reads);
314 ai = isl_union_access_info_set_schedule
315 (ai, isl_schedule_copy (scop->original_schedule));
316 flow = isl_union_access_info_compute_flow (ai);
317
318 isl_union_map *waw = isl_union_flow_get_must_dependence (flow);
319 isl_union_map *war = isl_union_flow_get_may_dependence (flow);
320 war = isl_union_map_subtract (war, isl_union_map_copy (waw));
321 isl_union_flow_free (flow);
322
323 raw = isl_union_map_coalesce (raw);
324 waw = isl_union_map_coalesce (waw);
325 war = isl_union_map_coalesce (war);
326
327 isl_union_map *dependences = raw;
328 dependences = isl_union_map_union (dependences, war);
329 dependences = isl_union_map_union (dependences, waw);
330 dependences = isl_union_map_coalesce (dependences);
331
332 if (dump_file)
333 {
334 fprintf (dump_file, "data dependences (\n");
335 print_isl_union_map (dump_file, dependences);
336 fprintf (dump_file, ")\n");
337 }
338
339 scop->dependence = dependences;
340}
341
26bd1f19 342#endif /* HAVE_isl */