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