]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/graphite-sese-to-poly.c
[PR89528] reset debug uses of return value when dropping dead RTL call
[thirdparty/gcc.git] / gcc / graphite-sese-to-poly.c
1 /* Conversion of SESE regions to Polyhedra.
2 Copyright (C) 2009-2019 Free Software Foundation, Inc.
3 Contributed by Sebastian Pop <sebastian.pop@amd.com>.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #define USES_ISL
22
23 #include "config.h"
24
25 #ifdef HAVE_isl
26
27 #include "system.h"
28 #include "coretypes.h"
29 #include "backend.h"
30 #include "cfghooks.h"
31 #include "tree.h"
32 #include "gimple.h"
33 #include "ssa.h"
34 #include "params.h"
35 #include "fold-const.h"
36 #include "gimple-iterator.h"
37 #include "gimplify.h"
38 #include "gimplify-me.h"
39 #include "tree-cfg.h"
40 #include "tree-ssa-loop-manip.h"
41 #include "tree-ssa-loop-niter.h"
42 #include "tree-ssa-loop.h"
43 #include "tree-into-ssa.h"
44 #include "tree-pass.h"
45 #include "cfgloop.h"
46 #include "tree-data-ref.h"
47 #include "tree-scalar-evolution.h"
48 #include "domwalk.h"
49 #include "tree-ssa-propagate.h"
50
51 #include <isl/constraint.h>
52 #include <isl/set.h>
53 #include <isl/map.h>
54 #include <isl/union_map.h>
55 #include <isl/constraint.h>
56 #include <isl/aff.h>
57 #include <isl/val.h>
58
59 #include "graphite.h"
60
61 /* Return an isl identifier for the polyhedral basic block PBB. */
62
63 static isl_id *
64 isl_id_for_pbb (scop_p s, poly_bb_p pbb)
65 {
66 char name[14];
67 snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
68 return isl_id_alloc (s->isl_context, name, pbb);
69 }
70
71 static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space);
72
73 /* Extract an affine expression from the chain of recurrence E. */
74
75 static isl_pw_aff *
76 extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space)
77 {
78 isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space));
79 isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space));
80 isl_local_space *ls = isl_local_space_from_space (space);
81 unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)) - 1;
82 isl_aff *loop = isl_aff_set_coefficient_si
83 (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1);
84 isl_pw_aff *l = isl_pw_aff_from_aff (loop);
85
86 /* Before multiplying, make sure that the result is affine. */
87 gcc_assert (isl_pw_aff_is_cst (rhs)
88 || isl_pw_aff_is_cst (l));
89
90 return isl_pw_aff_add (lhs, isl_pw_aff_mul (rhs, l));
91 }
92
93 /* Extract an affine expression from the mult_expr E. */
94
95 static isl_pw_aff *
96 extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space)
97 {
98 isl_pw_aff *lhs = extract_affine (s, TREE_OPERAND (e, 0),
99 isl_space_copy (space));
100 isl_pw_aff *rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
101
102 if (!isl_pw_aff_is_cst (lhs)
103 && !isl_pw_aff_is_cst (rhs))
104 {
105 isl_pw_aff_free (lhs);
106 isl_pw_aff_free (rhs);
107 return NULL;
108 }
109
110 return isl_pw_aff_mul (lhs, rhs);
111 }
112
113 /* Return an isl identifier from the name of the ssa_name E. */
114
115 static isl_id *
116 isl_id_for_ssa_name (scop_p s, tree e)
117 {
118 char name1[14];
119 snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e));
120 return isl_id_alloc (s->isl_context, name1, e);
121 }
122
123 /* Return an isl identifier for the data reference DR. Data references and
124 scalar references get the same isl_id. They need to be comparable and are
125 distinguished through the first dimension, which contains the alias set or
126 SSA_NAME_VERSION number. */
127
128 static isl_id *
129 isl_id_for_dr (scop_p s)
130 {
131 return isl_id_alloc (s->isl_context, "", 0);
132 }
133
134 /* Extract an affine expression from the ssa_name E. */
135
136 static isl_pw_aff *
137 extract_affine_name (int dimension, __isl_take isl_space *space)
138 {
139 isl_set *dom = isl_set_universe (isl_space_copy (space));
140 isl_aff *aff = isl_aff_zero_on_domain (isl_local_space_from_space (space));
141 aff = isl_aff_add_coefficient_si (aff, isl_dim_param, dimension, 1);
142 return isl_pw_aff_alloc (dom, aff);
143 }
144
145 /* Convert WI to a isl_val with CTX. */
146
147 static __isl_give isl_val *
148 isl_val_int_from_wi (isl_ctx *ctx, const widest_int &wi)
149 {
150 if (wi::neg_p (wi, SIGNED))
151 {
152 widest_int mwi = -wi;
153 return isl_val_neg (isl_val_int_from_chunks (ctx, mwi.get_len (),
154 sizeof (HOST_WIDE_INT),
155 mwi.get_val ()));
156 }
157 return isl_val_int_from_chunks (ctx, wi.get_len (), sizeof (HOST_WIDE_INT),
158 wi.get_val ());
159 }
160
161 /* Extract an affine expression from the gmp constant G. */
162
163 static isl_pw_aff *
164 extract_affine_wi (const widest_int &g, __isl_take isl_space *space)
165 {
166 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
167 isl_aff *aff = isl_aff_zero_on_domain (ls);
168 isl_set *dom = isl_set_universe (space);
169 isl_ctx *ct = isl_aff_get_ctx (aff);
170 isl_val *v = isl_val_int_from_wi (ct, g);
171 aff = isl_aff_add_constant_val (aff, v);
172
173 return isl_pw_aff_alloc (dom, aff);
174 }
175
176 /* Extract an affine expression from the integer_cst E. */
177
178 static isl_pw_aff *
179 extract_affine_int (tree e, __isl_take isl_space *space)
180 {
181 isl_pw_aff *res = extract_affine_wi (wi::to_widest (e), space);
182 return res;
183 }
184
185 /* Compute pwaff mod 2^width. */
186
187 static isl_pw_aff *
188 wrap (isl_pw_aff *pwaff, unsigned width)
189 {
190 isl_val *mod;
191
192 mod = isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff), width);
193 mod = isl_val_2exp (mod);
194 pwaff = isl_pw_aff_mod_val (pwaff, mod);
195
196 return pwaff;
197 }
198
199 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
200 Otherwise returns -1. */
201
202 static inline int
203 parameter_index_in_region (tree name, sese_info_p region)
204 {
205 int i;
206 tree p;
207 FOR_EACH_VEC_ELT (region->params, i, p)
208 if (p == name)
209 return i;
210 return -1;
211 }
212
213 /* Extract an affine expression from the tree E in the scop S. */
214
215 static isl_pw_aff *
216 extract_affine (scop_p s, tree e, __isl_take isl_space *space)
217 {
218 isl_pw_aff *lhs, *rhs, *res;
219
220 if (e == chrec_dont_know) {
221 isl_space_free (space);
222 return NULL;
223 }
224
225 tree type = TREE_TYPE (e);
226 switch (TREE_CODE (e))
227 {
228 case POLYNOMIAL_CHREC:
229 res = extract_affine_chrec (s, e, space);
230 break;
231
232 case MULT_EXPR:
233 res = extract_affine_mul (s, e, space);
234 break;
235
236 case POINTER_PLUS_EXPR:
237 {
238 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
239 /* The RHS of a pointer-plus expression is to be interpreted
240 as signed value. Try to look through a sign-changing conversion
241 first. */
242 tree tem = TREE_OPERAND (e, 1);
243 STRIP_NOPS (tem);
244 rhs = extract_affine (s, tem, space);
245 if (TYPE_UNSIGNED (TREE_TYPE (tem)))
246 rhs = wrap (rhs, TYPE_PRECISION (type) - 1);
247 res = isl_pw_aff_add (lhs, rhs);
248 break;
249 }
250
251 case PLUS_EXPR:
252 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
253 rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
254 res = isl_pw_aff_add (lhs, rhs);
255 break;
256
257 case MINUS_EXPR:
258 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
259 rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
260 res = isl_pw_aff_sub (lhs, rhs);
261 break;
262
263 case BIT_NOT_EXPR:
264 lhs = extract_affine (s, integer_minus_one_node, isl_space_copy (space));
265 rhs = extract_affine (s, TREE_OPERAND (e, 0), space);
266 res = isl_pw_aff_sub (lhs, rhs);
267 /* We need to always wrap the result of a bitwise operation. */
268 return wrap (res, TYPE_PRECISION (type) - (TYPE_UNSIGNED (type) ? 0 : 1));
269
270 case NEGATE_EXPR:
271 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
272 rhs = extract_affine (s, integer_minus_one_node, space);
273 res = isl_pw_aff_mul (lhs, rhs);
274 break;
275
276 case SSA_NAME:
277 {
278 gcc_assert (! defined_in_sese_p (e, s->scop_info->region));
279 int dim = parameter_index_in_region (e, s->scop_info);
280 gcc_assert (dim != -1);
281 /* No need to wrap a parameter. */
282 return extract_affine_name (dim, space);
283 }
284
285 case INTEGER_CST:
286 res = extract_affine_int (e, space);
287 /* No need to wrap a single integer. */
288 return res;
289
290 CASE_CONVERT:
291 {
292 tree itype = TREE_TYPE (TREE_OPERAND (e, 0));
293 res = extract_affine (s, TREE_OPERAND (e, 0), space);
294 /* Signed values, even if overflow is undefined, get modulo-reduced.
295 But only if not all values of the old type fit in the new. */
296 if (! TYPE_UNSIGNED (type)
297 && ((TYPE_UNSIGNED (itype)
298 && TYPE_PRECISION (type) <= TYPE_PRECISION (itype))
299 || TYPE_PRECISION (type) < TYPE_PRECISION (itype)))
300 res = wrap (res, TYPE_PRECISION (type) - 1);
301 else if (TYPE_UNSIGNED (type)
302 && (!TYPE_UNSIGNED (itype)
303 || TYPE_PRECISION (type) < TYPE_PRECISION (itype)))
304 res = wrap (res, TYPE_PRECISION (type));
305 return res;
306 }
307
308 case NON_LVALUE_EXPR:
309 res = extract_affine (s, TREE_OPERAND (e, 0), space);
310 break;
311
312 default:
313 gcc_unreachable ();
314 break;
315 }
316
317 /* For all wrapping arithmetic wrap the result. */
318 if (TYPE_OVERFLOW_WRAPS (type))
319 res = wrap (res, TYPE_PRECISION (type));
320
321 return res;
322 }
323
324 /* Returns a linear expression for tree T evaluated in PBB. */
325
326 static isl_pw_aff *
327 create_pw_aff_from_tree (poly_bb_p pbb, loop_p loop, tree t)
328 {
329 scop_p scop = PBB_SCOP (pbb);
330
331 t = cached_scalar_evolution_in_region (scop->scop_info->region, loop, t);
332
333 gcc_assert (!chrec_contains_undetermined (t));
334 gcc_assert (!automatically_generated_chrec_p (t));
335
336 return extract_affine (scop, t, isl_set_get_space (pbb->domain));
337 }
338
339 /* Add conditional statement STMT to pbb. CODE is used as the comparison
340 operator. This allows us to invert the condition or to handle
341 inequalities. */
342
343 static void
344 add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code)
345 {
346 loop_p loop = gimple_bb (stmt)->loop_father;
347 isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_lhs (stmt));
348 isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_rhs (stmt));
349
350 isl_set *cond;
351 switch (code)
352 {
353 case LT_EXPR:
354 cond = isl_pw_aff_lt_set (lhs, rhs);
355 break;
356
357 case GT_EXPR:
358 cond = isl_pw_aff_gt_set (lhs, rhs);
359 break;
360
361 case LE_EXPR:
362 cond = isl_pw_aff_le_set (lhs, rhs);
363 break;
364
365 case GE_EXPR:
366 cond = isl_pw_aff_ge_set (lhs, rhs);
367 break;
368
369 case EQ_EXPR:
370 cond = isl_pw_aff_eq_set (lhs, rhs);
371 break;
372
373 case NE_EXPR:
374 cond = isl_pw_aff_ne_set (lhs, rhs);
375 break;
376
377 default:
378 gcc_unreachable ();
379 }
380
381 cond = isl_set_coalesce (cond);
382 cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain));
383 pbb->domain = isl_set_coalesce (isl_set_intersect (pbb->domain, cond));
384 }
385
386 /* Add conditions to the domain of PBB. */
387
388 static void
389 add_conditions_to_domain (poly_bb_p pbb)
390 {
391 unsigned int i;
392 gimple *stmt;
393 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
394
395 if (GBB_CONDITIONS (gbb).is_empty ())
396 return;
397
398 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
399 switch (gimple_code (stmt))
400 {
401 case GIMPLE_COND:
402 {
403 /* Don't constrain on anything else than INTEGER_TYPE. */
404 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt))) != INTEGER_TYPE)
405 break;
406
407 gcond *cond_stmt = as_a <gcond *> (stmt);
408 enum tree_code code = gimple_cond_code (cond_stmt);
409
410 /* The conditions for ELSE-branches are inverted. */
411 if (!GBB_CONDITION_CASES (gbb)[i])
412 code = invert_tree_comparison (code, false);
413
414 add_condition_to_pbb (pbb, cond_stmt, code);
415 break;
416 }
417
418 default:
419 gcc_unreachable ();
420 break;
421 }
422 }
423
424 /* Add constraints on the possible values of parameter P from the type
425 of P. */
426
427 static void
428 add_param_constraints (scop_p scop, graphite_dim_t p, tree parameter)
429 {
430 tree type = TREE_TYPE (parameter);
431 wide_int min, max;
432
433 gcc_assert (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type));
434
435 if (INTEGRAL_TYPE_P (type)
436 && get_range_info (parameter, &min, &max) == VR_RANGE)
437 ;
438 else
439 {
440 min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
441 max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
442 }
443
444 isl_space *space = isl_set_get_space (scop->param_context);
445 isl_constraint *c = isl_inequality_alloc (isl_local_space_from_space (space));
446 isl_val *v = isl_val_int_from_wi (scop->isl_context,
447 widest_int::from (min, TYPE_SIGN (type)));
448 v = isl_val_neg (v);
449 c = isl_constraint_set_constant_val (c, v);
450 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, 1);
451 scop->param_context = isl_set_coalesce
452 (isl_set_add_constraint (scop->param_context, c));
453
454 space = isl_set_get_space (scop->param_context);
455 c = isl_inequality_alloc (isl_local_space_from_space (space));
456 v = isl_val_int_from_wi (scop->isl_context,
457 widest_int::from (max, TYPE_SIGN (type)));
458 c = isl_constraint_set_constant_val (c, v);
459 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, -1);
460 scop->param_context = isl_set_coalesce
461 (isl_set_add_constraint (scop->param_context, c));
462 }
463
464 /* Add a constrain to the ACCESSES polyhedron for the alias set of
465 data reference DR. ACCESSP_NB_DIMS is the dimension of the
466 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
467 domain. */
468
469 static isl_map *
470 pdr_add_alias_set (isl_map *acc, dr_info &dri)
471 {
472 isl_constraint *c = isl_equality_alloc
473 (isl_local_space_from_space (isl_map_get_space (acc)));
474 /* Positive numbers for all alias sets. */
475 c = isl_constraint_set_constant_si (c, -dri.alias_set);
476 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
477
478 return isl_map_add_constraint (acc, c);
479 }
480
481 /* Assign the affine expression INDEX to the output dimension POS of
482 MAP and return the result. */
483
484 static isl_map *
485 set_index (isl_map *map, int pos, isl_pw_aff *index)
486 {
487 isl_map *index_map;
488 int len = isl_map_dim (map, isl_dim_out);
489 isl_id *id;
490
491 index_map = isl_map_from_pw_aff (index);
492 index_map = isl_map_insert_dims (index_map, isl_dim_out, 0, pos);
493 index_map = isl_map_add_dims (index_map, isl_dim_out, len - pos - 1);
494
495 id = isl_map_get_tuple_id (map, isl_dim_out);
496 index_map = isl_map_set_tuple_id (index_map, isl_dim_out, id);
497 id = isl_map_get_tuple_id (map, isl_dim_in);
498 index_map = isl_map_set_tuple_id (index_map, isl_dim_in, id);
499
500 return isl_map_intersect (map, index_map);
501 }
502
503 /* Add to ACCESSES polyhedron equalities defining the access functions
504 to the memory. ACCESSP_NB_DIMS is the dimension of the ACCESSES
505 polyhedron, DOM_NB_DIMS is the dimension of the iteration domain.
506 PBB is the poly_bb_p that contains the data reference DR. */
507
508 static isl_map *
509 pdr_add_memory_accesses (isl_map *acc, dr_info &dri)
510 {
511 data_reference_p dr = dri.dr;
512 poly_bb_p pbb = dri.pbb;
513 int i, nb_subscripts = DR_NUM_DIMENSIONS (dr);
514 scop_p scop = PBB_SCOP (pbb);
515
516 for (i = 0; i < nb_subscripts; i++)
517 {
518 isl_pw_aff *aff;
519 tree afn = DR_ACCESS_FN (dr, i);
520
521 aff = extract_affine (scop, afn,
522 isl_space_domain (isl_map_get_space (acc)));
523 acc = set_index (acc, nb_subscripts - i , aff);
524 }
525
526 return isl_map_coalesce (acc);
527 }
528
529 /* Return true when the LOW and HIGH bounds of an array reference REF are valid
530 to extract constraints on accessed elements of the array. Returning false is
531 the conservative answer. */
532
533 static bool
534 bounds_are_valid (tree ref, tree low, tree high)
535 {
536 if (!high)
537 return false;
538
539 if (!tree_fits_shwi_p (low)
540 || !tree_fits_shwi_p (high))
541 return false;
542
543 /* 1-element arrays at end of structures may extend over
544 their declared size. */
545 if (array_at_struct_end_p (ref)
546 && operand_equal_p (low, high, 0))
547 return false;
548
549 /* Fortran has some arrays where high bound is -1 and low is 0. */
550 if (integer_onep (fold_build2 (LT_EXPR, boolean_type_node, high, low)))
551 return false;
552
553 return true;
554 }
555
556 /* Add constrains representing the size of the accessed data to the
557 ACCESSES polyhedron. ACCESSP_NB_DIMS is the dimension of the
558 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
559 domain. */
560
561 static isl_set *
562 pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop,
563 data_reference_p dr)
564 {
565 tree ref = DR_REF (dr);
566
567 int nb_subscripts = DR_NUM_DIMENSIONS (dr);
568 for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0))
569 {
570 if (TREE_CODE (ref) != ARRAY_REF)
571 return subscript_sizes;
572
573 tree low = array_ref_low_bound (ref);
574 tree high = array_ref_up_bound (ref);
575
576 if (!bounds_are_valid (ref, low, high))
577 continue;
578
579 isl_space *space = isl_set_get_space (subscript_sizes);
580 isl_pw_aff *lb = extract_affine_int (low, isl_space_copy (space));
581 isl_pw_aff *ub = extract_affine_int (high, isl_space_copy (space));
582
583 /* high >= 0 */
584 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub));
585 valid = isl_set_project_out (valid, isl_dim_set, 0,
586 isl_set_dim (valid, isl_dim_set));
587 scop->param_context = isl_set_coalesce
588 (isl_set_intersect (scop->param_context, valid));
589
590 isl_aff *aff
591 = isl_aff_zero_on_domain (isl_local_space_from_space (space));
592 aff = isl_aff_add_coefficient_si (aff, isl_dim_in, i + 1, 1);
593 isl_set *univ
594 = isl_set_universe (isl_space_domain (isl_aff_get_space (aff)));
595 isl_pw_aff *index = isl_pw_aff_alloc (univ, aff);
596
597 isl_id *id = isl_set_get_tuple_id (subscript_sizes);
598 lb = isl_pw_aff_set_tuple_id (lb, isl_dim_in, isl_id_copy (id));
599 ub = isl_pw_aff_set_tuple_id (ub, isl_dim_in, id);
600
601 /* low <= sub_i <= high */
602 isl_set *lbs = isl_pw_aff_ge_set (isl_pw_aff_copy (index), lb);
603 isl_set *ubs = isl_pw_aff_le_set (index, ub);
604 subscript_sizes = isl_set_intersect (subscript_sizes, lbs);
605 subscript_sizes = isl_set_intersect (subscript_sizes, ubs);
606 }
607
608 return isl_set_coalesce (subscript_sizes);
609 }
610
611 /* Build data accesses for DRI. */
612
613 static void
614 build_poly_dr (dr_info &dri)
615 {
616 isl_map *acc;
617 isl_set *subscript_sizes;
618 poly_bb_p pbb = dri.pbb;
619 data_reference_p dr = dri.dr;
620 scop_p scop = PBB_SCOP (pbb);
621 isl_id *id = isl_id_for_dr (scop);
622
623 {
624 isl_space *dc = isl_set_get_space (pbb->domain);
625 int nb_out = 1 + DR_NUM_DIMENSIONS (dr);
626 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
627 isl_dim_out, nb_out);
628
629 acc = isl_map_universe (space);
630 acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id));
631 }
632
633 acc = pdr_add_alias_set (acc, dri);
634 acc = pdr_add_memory_accesses (acc, dri);
635
636 {
637 int nb = 1 + DR_NUM_DIMENSIONS (dr);
638 isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb);
639
640 space = isl_space_set_tuple_id (space, isl_dim_set, id);
641 subscript_sizes = isl_set_nat_universe (space);
642 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
643 dri.alias_set);
644 subscript_sizes = pdr_add_data_dimensions (subscript_sizes, scop, dr);
645 }
646
647 new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE,
648 acc, subscript_sizes);
649 }
650
651 static void
652 build_poly_sr_1 (poly_bb_p pbb, gimple *stmt, tree var, enum poly_dr_type kind,
653 isl_map *acc, isl_set *subscript_sizes)
654 {
655 scop_p scop = PBB_SCOP (pbb);
656 /* Each scalar variables has a unique alias set number starting from
657 the maximum alias set assigned to a dr. */
658 int alias_set = scop->max_alias_set + SSA_NAME_VERSION (var);
659 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
660 alias_set);
661
662 /* Add a constrain to the ACCESSES polyhedron for the alias set of
663 data reference DR. */
664 isl_constraint *c
665 = isl_equality_alloc (isl_local_space_from_space (isl_map_get_space (acc)));
666 c = isl_constraint_set_constant_si (c, -alias_set);
667 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
668
669 new_poly_dr (pbb, stmt, kind, isl_map_add_constraint (acc, c),
670 subscript_sizes);
671 }
672
673 /* Record all cross basic block scalar variables in PBB. */
674
675 static void
676 build_poly_sr (poly_bb_p pbb)
677 {
678 scop_p scop = PBB_SCOP (pbb);
679 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
680 vec<scalar_use> &reads = gbb->read_scalar_refs;
681 vec<tree> &writes = gbb->write_scalar_refs;
682
683 isl_space *dc = isl_set_get_space (pbb->domain);
684 int nb_out = 1;
685 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
686 isl_dim_out, nb_out);
687 isl_id *id = isl_id_for_dr (scop);
688 space = isl_space_set_tuple_id (space, isl_dim_set, isl_id_copy (id));
689 isl_map *acc = isl_map_universe (isl_space_copy (space));
690 acc = isl_map_set_tuple_id (acc, isl_dim_out, id);
691 isl_set *subscript_sizes = isl_set_nat_universe (space);
692
693 int i;
694 tree var;
695 FOR_EACH_VEC_ELT (writes, i, var)
696 build_poly_sr_1 (pbb, SSA_NAME_DEF_STMT (var), var, PDR_WRITE,
697 isl_map_copy (acc), isl_set_copy (subscript_sizes));
698
699 scalar_use *use;
700 FOR_EACH_VEC_ELT (reads, i, use)
701 build_poly_sr_1 (pbb, use->first, use->second, PDR_READ, isl_map_copy (acc),
702 isl_set_copy (subscript_sizes));
703
704 isl_map_free (acc);
705 isl_set_free (subscript_sizes);
706 }
707
708 /* Build data references in SCOP. */
709
710 static void
711 build_scop_drs (scop_p scop)
712 {
713 int i;
714 dr_info *dri;
715 FOR_EACH_VEC_ELT (scop->drs, i, dri)
716 build_poly_dr (*dri);
717
718 poly_bb_p pbb;
719 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
720 build_poly_sr (pbb);
721 }
722
723 /* Add to the iteration DOMAIN one extra dimension for LOOP->num. */
724
725 static isl_set *
726 add_iter_domain_dimension (__isl_take isl_set *domain, loop_p loop, scop_p scop)
727 {
728 int loop_index = isl_set_dim (domain, isl_dim_set);
729 domain = isl_set_add_dims (domain, isl_dim_set, 1);
730 char name[50];
731 snprintf (name, sizeof(name), "i%d", loop->num);
732 isl_id *label = isl_id_alloc (scop->isl_context, name, NULL);
733 return isl_set_set_dim_id (domain, isl_dim_set, loop_index, label);
734 }
735
736 /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */
737
738 static isl_set *
739 add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop,
740 loop_p context)
741 {
742 if (loop == context)
743 return domain;
744 const sese_l &region = scop->scop_info->region;
745 if (!loop_in_sese_p (loop, region))
746 return domain;
747
748 /* Recursion all the way up to the context loop. */
749 domain = add_loop_constraints (scop, domain, loop_outer (loop), context);
750
751 /* Then, build constraints over the loop in post-order: outer to inner. */
752
753 int loop_index = isl_set_dim (domain, isl_dim_set);
754 if (dump_file)
755 fprintf (dump_file, "[sese-to-poly] adding one extra dimension to the "
756 "domain for loop_%d.\n", loop->num);
757 domain = add_iter_domain_dimension (domain, loop, scop);
758 isl_space *space = isl_set_get_space (domain);
759
760 /* 0 <= loop_i */
761 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
762 isl_constraint *c = isl_inequality_alloc (ls);
763 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, 1);
764 if (dump_file)
765 {
766 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
767 print_isl_constraint (dump_file, c);
768 }
769 domain = isl_set_add_constraint (domain, c);
770
771 tree nb_iters = number_of_latch_executions (loop);
772 if (TREE_CODE (nb_iters) == INTEGER_CST)
773 {
774 /* loop_i <= cst_nb_iters */
775 isl_local_space *ls = isl_local_space_from_space (space);
776 isl_constraint *c = isl_inequality_alloc (ls);
777 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
778 isl_val *v
779 = isl_val_int_from_wi (scop->isl_context, wi::to_widest (nb_iters));
780 c = isl_constraint_set_constant_val (c, v);
781 return isl_set_add_constraint (domain, c);
782 }
783 /* loop_i <= expr_nb_iters */
784 gcc_assert (!chrec_contains_undetermined (nb_iters));
785 nb_iters = cached_scalar_evolution_in_region (region, loop, nb_iters);
786 gcc_assert (!chrec_contains_undetermined (nb_iters));
787
788 isl_pw_aff *aff_nb_iters = extract_affine (scop, nb_iters,
789 isl_space_copy (space));
790 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters));
791 valid = isl_set_project_out (valid, isl_dim_set, 0,
792 isl_set_dim (valid, isl_dim_set));
793
794 if (valid)
795 scop->param_context = isl_set_intersect (scop->param_context, valid);
796
797 ls = isl_local_space_from_space (isl_space_copy (space));
798 isl_aff *loop_i = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls),
799 isl_dim_in, loop_index, 1);
800 isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i),
801 isl_pw_aff_copy (aff_nb_iters));
802 if (dump_file)
803 {
804 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
805 print_isl_set (dump_file, le);
806 }
807 domain = isl_set_intersect (domain, le);
808
809 widest_int nit;
810 if (!max_stmt_executions (loop, &nit))
811 {
812 isl_pw_aff_free (aff_nb_iters);
813 isl_space_free (space);
814 return domain;
815 }
816
817 /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we
818 do not know whether the loop executes at least once. */
819 --nit;
820
821 isl_pw_aff *approx = extract_affine_wi (nit, isl_space_copy (space));
822 isl_set *x = isl_pw_aff_ge_set (approx, aff_nb_iters);
823 x = isl_set_project_out (x, isl_dim_set, 0,
824 isl_set_dim (x, isl_dim_set));
825 scop->param_context = isl_set_intersect (scop->param_context, x);
826
827 ls = isl_local_space_from_space (space);
828 c = isl_inequality_alloc (ls);
829 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
830 isl_val *v = isl_val_int_from_wi (scop->isl_context, nit);
831 c = isl_constraint_set_constant_val (c, v);
832
833 if (dump_file)
834 {
835 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
836 print_isl_constraint (dump_file, c);
837 }
838
839 return isl_set_add_constraint (domain, c);
840 }
841
842 /* Builds the original iteration domains for each pbb in the SCOP. */
843
844 static int
845 build_iteration_domains (scop_p scop, __isl_keep isl_set *context,
846 int index, loop_p context_loop)
847 {
848 loop_p current = pbb_loop (scop->pbbs[index]);
849 isl_set *domain = isl_set_copy (context);
850 domain = add_loop_constraints (scop, domain, current, context_loop);
851 const sese_l &region = scop->scop_info->region;
852
853 int i;
854 poly_bb_p pbb;
855 FOR_EACH_VEC_ELT_FROM (scop->pbbs, i, pbb, index)
856 {
857 loop_p loop = pbb_loop (pbb);
858 if (current == loop)
859 {
860 pbb->iterators = isl_set_copy (domain);
861 pbb->domain = isl_set_copy (domain);
862 pbb->domain = isl_set_set_tuple_id (pbb->domain,
863 isl_id_for_pbb (scop, pbb));
864 add_conditions_to_domain (pbb);
865
866 if (dump_file)
867 {
868 fprintf (dump_file, "[sese-to-poly] set pbb_%d->domain: ",
869 pbb_index (pbb));
870 print_isl_set (dump_file, domain);
871 }
872 continue;
873 }
874
875 while (loop_in_sese_p (loop, region)
876 && current != loop)
877 loop = loop_outer (loop);
878
879 if (current != loop)
880 {
881 /* A statement in a different loop nest than CURRENT loop. */
882 isl_set_free (domain);
883 return i;
884 }
885
886 /* A statement nested in the CURRENT loop. */
887 i = build_iteration_domains (scop, domain, i, current);
888 i--;
889 }
890
891 isl_set_free (domain);
892 return i;
893 }
894
895 /* Assign dimension for each parameter in SCOP and add constraints for the
896 parameters. */
897
898 static void
899 build_scop_context (scop_p scop)
900 {
901 sese_info_p region = scop->scop_info;
902 unsigned nbp = sese_nb_params (region);
903 isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0);
904
905 unsigned i;
906 tree e;
907 FOR_EACH_VEC_ELT (region->params, i, e)
908 space = isl_space_set_dim_id (space, isl_dim_param, i,
909 isl_id_for_ssa_name (scop, e));
910
911 scop->param_context = isl_set_universe (space);
912
913 FOR_EACH_VEC_ELT (region->params, i, e)
914 add_param_constraints (scop, i, e);
915 }
916
917 /* Return true when loop A is nested in loop B. */
918
919 static bool
920 nested_in (loop_p a, loop_p b)
921 {
922 return b == find_common_loop (a, b);
923 }
924
925 /* Return the loop at a specific SCOP->pbbs[*INDEX]. */
926 static loop_p
927 loop_at (scop_p scop, int *index)
928 {
929 return pbb_loop (scop->pbbs[*index]);
930 }
931
932 /* Return the index of any pbb belonging to loop or a subloop of A. */
933
934 static int
935 index_outermost_in_loop (loop_p a, scop_p scop)
936 {
937 int i, outermost = -1;
938 int last_depth = -1;
939 poly_bb_p pbb;
940 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
941 if (nested_in (pbb_loop (pbb), a)
942 && (last_depth == -1
943 || last_depth > (int) loop_depth (pbb_loop (pbb))))
944 {
945 outermost = i;
946 last_depth = loop_depth (pbb_loop (pbb));
947 }
948 return outermost;
949 }
950
951 /* Return the index of any pbb belonging to loop or a subloop of A. */
952
953 static int
954 index_pbb_in_loop (loop_p a, scop_p scop)
955 {
956 int i;
957 poly_bb_p pbb;
958 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
959 if (pbb_loop (pbb) == a)
960 return i;
961 return -1;
962 }
963
964 static poly_bb_p
965 outermost_pbb_in (loop_p loop, scop_p scop)
966 {
967 int x = index_pbb_in_loop (loop, scop);
968 if (x == -1)
969 x = index_outermost_in_loop (loop, scop);
970 return scop->pbbs[x];
971 }
972
973 static isl_schedule *
974 add_in_sequence (__isl_take isl_schedule *a, __isl_take isl_schedule *b)
975 {
976 gcc_assert (a || b);
977
978 if (!a)
979 return b;
980
981 if (!b)
982 return a;
983
984 return isl_schedule_sequence (a, b);
985 }
986
987 struct map_to_dimension_data {
988 int n;
989 isl_union_pw_multi_aff *res;
990 };
991
992 /* Create a function that maps the elements of SET to its N-th dimension and add
993 it to USER->res. */
994
995 static isl_stat
996 add_outer_projection (__isl_take isl_set *set, void *user)
997 {
998 struct map_to_dimension_data *data = (struct map_to_dimension_data *) user;
999 int dim = isl_set_dim (set, isl_dim_set);
1000 isl_space *space = isl_set_get_space (set);
1001
1002 gcc_assert (dim >= data->n);
1003 isl_pw_multi_aff *pma
1004 = isl_pw_multi_aff_project_out_map (space, isl_dim_set, data->n,
1005 dim - data->n);
1006 data->res = isl_union_pw_multi_aff_add_pw_multi_aff (data->res, pma);
1007
1008 isl_set_free (set);
1009 return isl_stat_ok;
1010 }
1011
1012 /* Return SET in which all inner dimensions above N are removed. */
1013
1014 static isl_multi_union_pw_aff *
1015 outer_projection_mupa (__isl_take isl_union_set *set, int n)
1016 {
1017 gcc_assert (n >= 0);
1018 gcc_assert (set);
1019 gcc_assert (!isl_union_set_is_empty (set));
1020
1021 isl_space *space = isl_union_set_get_space (set);
1022 isl_union_pw_multi_aff *pwaff = isl_union_pw_multi_aff_empty (space);
1023
1024 struct map_to_dimension_data data = {n, pwaff};
1025
1026 if (isl_union_set_foreach_set (set, &add_outer_projection, &data) < 0)
1027 data.res = isl_union_pw_multi_aff_free (data.res);
1028
1029 isl_union_set_free (set);
1030 return isl_multi_union_pw_aff_from_union_pw_multi_aff (data.res);
1031 }
1032
1033 /* Embed SCHEDULE in the constraints of the LOOP domain. */
1034
1035 static isl_schedule *
1036 add_loop_schedule (__isl_take isl_schedule *schedule, loop_p loop,
1037 scop_p scop)
1038 {
1039 poly_bb_p pbb = outermost_pbb_in (loop, scop);
1040 isl_set *iterators = pbb->iterators;
1041
1042 int empty = isl_set_is_empty (iterators);
1043 if (empty < 0 || empty)
1044 return empty < 0 ? isl_schedule_free (schedule) : schedule;
1045
1046 isl_union_set *domain = isl_schedule_get_domain (schedule);
1047 /* We cannot apply an empty domain to pbbs in this loop so return early. */
1048 if (isl_union_set_is_empty (domain))
1049 {
1050 isl_union_set_free (domain);
1051 return schedule;
1052 }
1053
1054 isl_space *space = isl_set_get_space (iterators);
1055 int loop_index = isl_space_dim (space, isl_dim_set) - 1;
1056
1057 loop_p ploop = pbb_loop (pbb);
1058 while (loop != ploop)
1059 {
1060 --loop_index;
1061 ploop = loop_outer (ploop);
1062 }
1063
1064 isl_local_space *ls = isl_local_space_from_space (space);
1065 isl_aff *aff = isl_aff_var_on_domain (ls, isl_dim_set, loop_index);
1066 isl_multi_aff *prefix = isl_multi_aff_from_aff (aff);
1067 char name[50];
1068 snprintf (name, sizeof(name), "L_%d", loop->num);
1069 isl_id *label = isl_id_alloc (isl_schedule_get_ctx (schedule),
1070 name, NULL);
1071 prefix = isl_multi_aff_set_tuple_id (prefix, isl_dim_out, label);
1072
1073 int n = isl_multi_aff_dim (prefix, isl_dim_in);
1074 isl_multi_union_pw_aff *mupa = outer_projection_mupa (domain, n);
1075 mupa = isl_multi_union_pw_aff_apply_multi_aff (mupa, prefix);
1076 return isl_schedule_insert_partial_schedule (schedule, mupa);
1077 }
1078
1079 /* Build schedule for the pbb at INDEX. */
1080
1081 static isl_schedule *
1082 build_schedule_pbb (scop_p scop, int *index)
1083 {
1084 poly_bb_p pbb = scop->pbbs[*index];
1085 ++*index;
1086 isl_set *domain = isl_set_copy (pbb->domain);
1087 isl_union_set *ud = isl_union_set_from_set (domain);
1088 return isl_schedule_from_domain (ud);
1089 }
1090
1091 static isl_schedule *build_schedule_loop_nest (scop_p, int *, loop_p);
1092
1093 /* Build the schedule of the loop containing the SCOP pbb at INDEX. */
1094
1095 static isl_schedule *
1096 build_schedule_loop (scop_p scop, int *index)
1097 {
1098 int max = scop->pbbs.length ();
1099 gcc_assert (*index < max);
1100 loop_p loop = loop_at (scop, index);
1101
1102 isl_schedule *s = NULL;
1103 while (nested_in (loop_at (scop, index), loop))
1104 {
1105 if (loop == loop_at (scop, index))
1106 s = add_in_sequence (s, build_schedule_pbb (scop, index));
1107 else
1108 s = add_in_sequence (s, build_schedule_loop_nest (scop, index, loop));
1109
1110 if (*index == max)
1111 break;
1112 }
1113
1114 return add_loop_schedule (s, loop, scop);
1115 }
1116
1117 /* S is the schedule of the loop LOOP. Embed the schedule S in all outer loops.
1118 When CONTEXT_LOOP is null, embed the schedule in all loops contained in the
1119 SCOP surrounding LOOP. When CONTEXT_LOOP is non null, only embed S in the
1120 maximal loop nest contained within CONTEXT_LOOP. */
1121
1122 static isl_schedule *
1123 embed_in_surrounding_loops (__isl_take isl_schedule *s, scop_p scop,
1124 loop_p loop, int *index, loop_p context_loop)
1125 {
1126 loop_p outer = loop_outer (loop);
1127 sese_l region = scop->scop_info->region;
1128 if (context_loop == outer
1129 || !loop_in_sese_p (outer, region))
1130 return s;
1131
1132 int max = scop->pbbs.length ();
1133 if (*index == max
1134 || (context_loop && !nested_in (loop_at (scop, index), context_loop))
1135 || (!context_loop
1136 && !loop_in_sese_p (find_common_loop (outer, loop_at (scop, index)),
1137 region)))
1138 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop),
1139 scop, outer, index, context_loop);
1140
1141 bool a_pbb;
1142 while ((a_pbb = (outer == loop_at (scop, index)))
1143 || nested_in (loop_at (scop, index), outer))
1144 {
1145 if (a_pbb)
1146 s = add_in_sequence (s, build_schedule_pbb (scop, index));
1147 else
1148 s = add_in_sequence (s, build_schedule_loop (scop, index));
1149
1150 if (*index == max)
1151 break;
1152 }
1153
1154 /* We reached the end of the OUTER loop: embed S in OUTER. */
1155 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), scop,
1156 outer, index, context_loop);
1157 }
1158
1159 /* Build schedule for the full loop nest containing the pbb at INDEX. When
1160 CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP
1161 surrounding the pbb. When CONTEXT_LOOP is non null, only build the maximal loop
1162 nest contained within CONTEXT_LOOP. */
1163
1164 static isl_schedule *
1165 build_schedule_loop_nest (scop_p scop, int *index, loop_p context_loop)
1166 {
1167 gcc_assert (*index != (int) scop->pbbs.length ());
1168
1169 loop_p loop = loop_at (scop, index);
1170 isl_schedule *s = build_schedule_loop (scop, index);
1171 return embed_in_surrounding_loops (s, scop, loop, index, context_loop);
1172 }
1173
1174 /* Build the schedule of the SCOP. */
1175
1176 static void
1177 build_original_schedule (scop_p scop)
1178 {
1179 int i = 0;
1180 int n = scop->pbbs.length ();
1181 while (i < n)
1182 {
1183 poly_bb_p pbb = scop->pbbs[i];
1184 isl_schedule *s = NULL;
1185 if (!loop_in_sese_p (pbb_loop (pbb), scop->scop_info->region))
1186 s = build_schedule_pbb (scop, &i);
1187 else
1188 s = build_schedule_loop_nest (scop, &i, NULL);
1189
1190 scop->original_schedule = add_in_sequence (scop->original_schedule, s);
1191 }
1192
1193 if (dump_file)
1194 {
1195 fprintf (dump_file, "[sese-to-poly] original schedule:\n");
1196 print_isl_schedule (dump_file, scop->original_schedule);
1197 }
1198 }
1199
1200 /* Builds the polyhedral representation for a SESE region. */
1201
1202 bool
1203 build_poly_scop (scop_p scop)
1204 {
1205 int old_err = isl_options_get_on_error (scop->isl_context);
1206 isl_options_set_on_error (scop->isl_context, ISL_ON_ERROR_CONTINUE);
1207
1208 build_scop_context (scop);
1209
1210 unsigned i = 0;
1211 unsigned n = scop->pbbs.length ();
1212 while (i < n)
1213 i = build_iteration_domains (scop, scop->param_context, i, NULL);
1214
1215 build_scop_drs (scop);
1216 build_original_schedule (scop);
1217
1218 enum isl_error err = isl_ctx_last_error (scop->isl_context);
1219 isl_ctx_reset_error (scop->isl_context);
1220 isl_options_set_on_error (scop->isl_context, old_err);
1221 if (err != isl_error_none
1222 && dump_enabled_p ())
1223 dump_printf (MSG_MISSED_OPTIMIZATION,
1224 "ISL error while building poly scop\n");
1225
1226 return err == isl_error_none;
1227 }
1228 #endif /* HAVE_isl */