Relocation (= move+destroy)
[official-gcc.git] / gcc / graphite-sese-to-poly.c
blob69898d4ffd8203a1b0d21fee3a0b9c3b2d76294b
1 /* Conversion of SESE regions to Polyhedra.
2 Copyright (C) 2009-2018 Free Software Foundation, Inc.
3 Contributed by Sebastian Pop <sebastian.pop@amd.com>.
5 This file is part of GCC.
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.
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.
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/>. */
21 #define USES_ISL
23 #include "config.h"
25 #ifdef HAVE_isl
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"
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>
59 #include "graphite.h"
61 /* Return an isl identifier for the polyhedral basic block PBB. */
63 static isl_id *
64 isl_id_for_pbb (scop_p s, poly_bb_p pbb)
66 char name[14];
67 snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
68 return isl_id_alloc (s->isl_context, name, pbb);
71 static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space);
73 /* Extract an affine expression from the chain of recurrence E. */
75 static isl_pw_aff *
76 extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space)
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);
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));
90 return isl_pw_aff_add (lhs, isl_pw_aff_mul (rhs, l));
93 /* Extract an affine expression from the mult_expr E. */
95 static isl_pw_aff *
96 extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space)
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);
102 if (!isl_pw_aff_is_cst (lhs)
103 && !isl_pw_aff_is_cst (rhs))
105 isl_pw_aff_free (lhs);
106 isl_pw_aff_free (rhs);
107 return NULL;
110 return isl_pw_aff_mul (lhs, rhs);
113 /* Return an isl identifier from the name of the ssa_name E. */
115 static isl_id *
116 isl_id_for_ssa_name (scop_p s, tree e)
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);
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. */
128 static isl_id *
129 isl_id_for_dr (scop_p s)
131 return isl_id_alloc (s->isl_context, "", 0);
134 /* Extract an affine expression from the ssa_name E. */
136 static isl_pw_aff *
137 extract_affine_name (int dimension, __isl_take isl_space *space)
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);
145 /* Convert WI to a isl_val with CTX. */
147 static __isl_give isl_val *
148 isl_val_int_from_wi (isl_ctx *ctx, const widest_int &wi)
150 if (wi::neg_p (wi, SIGNED))
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 ()));
157 return isl_val_int_from_chunks (ctx, wi.get_len (), sizeof (HOST_WIDE_INT),
158 wi.get_val ());
161 /* Extract an affine expression from the gmp constant G. */
163 static isl_pw_aff *
164 extract_affine_wi (const widest_int &g, __isl_take isl_space *space)
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);
173 return isl_pw_aff_alloc (dom, aff);
176 /* Extract an affine expression from the integer_cst E. */
178 static isl_pw_aff *
179 extract_affine_int (tree e, __isl_take isl_space *space)
181 isl_pw_aff *res = extract_affine_wi (wi::to_widest (e), space);
182 return res;
185 /* Compute pwaff mod 2^width. */
187 static isl_pw_aff *
188 wrap (isl_pw_aff *pwaff, unsigned width)
190 isl_val *mod;
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);
196 return pwaff;
199 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
200 Otherwise returns -1. */
202 static inline int
203 parameter_index_in_region (tree name, sese_info_p region)
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;
213 /* Extract an affine expression from the tree E in the scop S. */
215 static isl_pw_aff *
216 extract_affine (scop_p s, tree e, __isl_take isl_space *space)
218 isl_pw_aff *lhs, *rhs, *res;
220 if (e == chrec_dont_know) {
221 isl_space_free (space);
222 return NULL;
225 tree type = TREE_TYPE (e);
226 switch (TREE_CODE (e))
228 case POLYNOMIAL_CHREC:
229 res = extract_affine_chrec (s, e, space);
230 break;
232 case MULT_EXPR:
233 res = extract_affine_mul (s, e, space);
234 break;
236 case POINTER_PLUS_EXPR:
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;
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;
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;
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));
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;
276 case SSA_NAME:
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);
285 case INTEGER_CST:
286 res = extract_affine_int (e, space);
287 /* No need to wrap a single integer. */
288 return res;
290 CASE_CONVERT:
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;
308 case NON_LVALUE_EXPR:
309 res = extract_affine (s, TREE_OPERAND (e, 0), space);
310 break;
312 default:
313 gcc_unreachable ();
314 break;
317 /* For all wrapping arithmetic wrap the result. */
318 if (TYPE_OVERFLOW_WRAPS (type))
319 res = wrap (res, TYPE_PRECISION (type));
321 return res;
324 /* Returns a linear expression for tree T evaluated in PBB. */
326 static isl_pw_aff *
327 create_pw_aff_from_tree (poly_bb_p pbb, loop_p loop, tree t)
329 scop_p scop = PBB_SCOP (pbb);
331 t = scalar_evolution_in_region (scop->scop_info->region, loop, t);
333 gcc_assert (!chrec_contains_undetermined (t));
334 gcc_assert (!automatically_generated_chrec_p (t));
336 return extract_affine (scop, t, isl_set_get_space (pbb->domain));
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. */
343 static void
344 add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code)
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));
350 isl_set *cond;
351 switch (code)
353 case LT_EXPR:
354 cond = isl_pw_aff_lt_set (lhs, rhs);
355 break;
357 case GT_EXPR:
358 cond = isl_pw_aff_gt_set (lhs, rhs);
359 break;
361 case LE_EXPR:
362 cond = isl_pw_aff_le_set (lhs, rhs);
363 break;
365 case GE_EXPR:
366 cond = isl_pw_aff_ge_set (lhs, rhs);
367 break;
369 case EQ_EXPR:
370 cond = isl_pw_aff_eq_set (lhs, rhs);
371 break;
373 case NE_EXPR:
374 cond = isl_pw_aff_ne_set (lhs, rhs);
375 break;
377 default:
378 gcc_unreachable ();
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));
386 /* Add conditions to the domain of PBB. */
388 static void
389 add_conditions_to_domain (poly_bb_p pbb)
391 unsigned int i;
392 gimple *stmt;
393 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
395 if (GBB_CONDITIONS (gbb).is_empty ())
396 return;
398 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
399 switch (gimple_code (stmt))
401 case GIMPLE_COND:
403 /* Don't constrain on anything else than INTEGER_TYPE. */
404 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt))) != INTEGER_TYPE)
405 break;
407 gcond *cond_stmt = as_a <gcond *> (stmt);
408 enum tree_code code = gimple_cond_code (cond_stmt);
410 /* The conditions for ELSE-branches are inverted. */
411 if (!GBB_CONDITION_CASES (gbb)[i])
412 code = invert_tree_comparison (code, false);
414 add_condition_to_pbb (pbb, cond_stmt, code);
415 break;
418 default:
419 gcc_unreachable ();
420 break;
424 /* Add constraints on the possible values of parameter P from the type
425 of P. */
427 static void
428 add_param_constraints (scop_p scop, graphite_dim_t p, tree parameter)
430 tree type = TREE_TYPE (parameter);
431 wide_int min, max;
433 gcc_assert (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type));
435 if (INTEGRAL_TYPE_P (type)
436 && get_range_info (parameter, &min, &max) == VR_RANGE)
438 else
440 min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
441 max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
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));
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));
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. */
469 static isl_map *
470 pdr_add_alias_set (isl_map *acc, dr_info &dri)
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);
478 return isl_map_add_constraint (acc, c);
481 /* Assign the affine expression INDEX to the output dimension POS of
482 MAP and return the result. */
484 static isl_map *
485 set_index (isl_map *map, int pos, isl_pw_aff *index)
487 isl_map *index_map;
488 int len = isl_map_dim (map, isl_dim_out);
489 isl_id *id;
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);
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);
500 return isl_map_intersect (map, index_map);
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. */
508 static isl_map *
509 pdr_add_memory_accesses (isl_map *acc, dr_info &dri)
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);
516 for (i = 0; i < nb_subscripts; i++)
518 isl_pw_aff *aff;
519 tree afn = DR_ACCESS_FN (dr, i);
521 aff = extract_affine (scop, afn,
522 isl_space_domain (isl_map_get_space (acc)));
523 acc = set_index (acc, nb_subscripts - i , aff);
526 return isl_map_coalesce (acc);
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. */
533 static bool
534 bounds_are_valid (tree ref, tree low, tree high)
536 if (!high)
537 return false;
539 if (!tree_fits_shwi_p (low)
540 || !tree_fits_shwi_p (high))
541 return false;
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;
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;
553 return true;
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. */
561 static isl_set *
562 pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop,
563 data_reference_p dr)
565 tree ref = DR_REF (dr);
567 int nb_subscripts = DR_NUM_DIMENSIONS (dr);
568 for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0))
570 if (TREE_CODE (ref) != ARRAY_REF)
571 return subscript_sizes;
573 tree low = array_ref_low_bound (ref);
574 tree high = array_ref_up_bound (ref);
576 if (!bounds_are_valid (ref, low, high))
577 continue;
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));
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));
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);
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);
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);
608 return isl_set_coalesce (subscript_sizes);
611 /* Build data accesses for DRI. */
613 static void
614 build_poly_dr (dr_info &dri)
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);
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);
629 acc = isl_map_universe (space);
630 acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id));
633 acc = pdr_add_alias_set (acc, dri);
634 acc = pdr_add_memory_accesses (acc, dri);
637 int nb = 1 + DR_NUM_DIMENSIONS (dr);
638 isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb);
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);
647 new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE,
648 acc, subscript_sizes);
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)
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);
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);
669 new_poly_dr (pbb, stmt, kind, isl_map_add_constraint (acc, c),
670 subscript_sizes);
673 /* Record all cross basic block scalar variables in PBB. */
675 static void
676 build_poly_sr (poly_bb_p pbb)
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;
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);
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));
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));
704 isl_map_free (acc);
705 isl_set_free (subscript_sizes);
708 /* Build data references in SCOP. */
710 static void
711 build_scop_drs (scop_p scop)
713 int i;
714 dr_info *dri;
715 FOR_EACH_VEC_ELT (scop->drs, i, dri)
716 build_poly_dr (*dri);
718 poly_bb_p pbb;
719 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
720 build_poly_sr (pbb);
723 /* Add to the iteration DOMAIN one extra dimension for LOOP->num. */
725 static isl_set *
726 add_iter_domain_dimension (__isl_take isl_set *domain, loop_p loop, scop_p scop)
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);
736 /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */
738 static isl_set *
739 add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop,
740 loop_p context)
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;
748 /* Recursion all the way up to the context loop. */
749 domain = add_loop_constraints (scop, domain, loop_outer (loop), context);
751 /* Then, build constraints over the loop in post-order: outer to inner. */
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);
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)
766 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
767 print_isl_constraint (dump_file, c);
769 domain = isl_set_add_constraint (domain, c);
771 tree nb_iters = number_of_latch_executions (loop);
772 if (TREE_CODE (nb_iters) == INTEGER_CST)
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);
783 /* loop_i <= expr_nb_iters */
784 gcc_assert (!chrec_contains_undetermined (nb_iters));
785 nb_iters = scalar_evolution_in_region (region, loop, nb_iters);
786 gcc_assert (!chrec_contains_undetermined (nb_iters));
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));
794 if (valid)
795 scop->param_context = isl_set_intersect (scop->param_context, valid);
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)
804 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
805 print_isl_set (dump_file, le);
807 domain = isl_set_intersect (domain, le);
809 widest_int nit;
810 if (!max_stmt_executions (loop, &nit))
812 isl_pw_aff_free (aff_nb_iters);
813 isl_space_free (space);
814 return domain;
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;
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);
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);
833 if (dump_file)
835 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
836 print_isl_constraint (dump_file, c);
839 return isl_set_add_constraint (domain, c);
842 /* Builds the original iteration domains for each pbb in the SCOP. */
844 static int
845 build_iteration_domains (scop_p scop, __isl_keep isl_set *context,
846 int index, loop_p context_loop)
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;
853 int i;
854 poly_bb_p pbb;
855 FOR_EACH_VEC_ELT_FROM (scop->pbbs, i, pbb, index)
857 loop_p loop = pbb_loop (pbb);
858 if (current == loop)
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);
866 if (dump_file)
868 fprintf (dump_file, "[sese-to-poly] set pbb_%d->domain: ",
869 pbb_index (pbb));
870 print_isl_set (dump_file, domain);
872 continue;
875 while (loop_in_sese_p (loop, region)
876 && current != loop)
877 loop = loop_outer (loop);
879 if (current != loop)
881 /* A statement in a different loop nest than CURRENT loop. */
882 isl_set_free (domain);
883 return i;
886 /* A statement nested in the CURRENT loop. */
887 i = build_iteration_domains (scop, domain, i, current);
888 i--;
891 isl_set_free (domain);
892 return i;
895 /* Assign dimension for each parameter in SCOP and add constraints for the
896 parameters. */
898 static void
899 build_scop_context (scop_p scop)
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);
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));
911 scop->param_context = isl_set_universe (space);
913 FOR_EACH_VEC_ELT (region->params, i, e)
914 add_param_constraints (scop, i, e);
917 /* Return true when loop A is nested in loop B. */
919 static bool
920 nested_in (loop_p a, loop_p b)
922 return b == find_common_loop (a, b);
925 /* Return the loop at a specific SCOP->pbbs[*INDEX]. */
926 static loop_p
927 loop_at (scop_p scop, int *index)
929 return pbb_loop (scop->pbbs[*index]);
932 /* Return the index of any pbb belonging to loop or a subloop of A. */
934 static int
935 index_outermost_in_loop (loop_p a, scop_p scop)
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))))
945 outermost = i;
946 last_depth = loop_depth (pbb_loop (pbb));
948 return outermost;
951 /* Return the index of any pbb belonging to loop or a subloop of A. */
953 static int
954 index_pbb_in_loop (loop_p a, scop_p scop)
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;
964 static poly_bb_p
965 outermost_pbb_in (loop_p loop, scop_p scop)
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];
973 static isl_schedule *
974 add_in_sequence (__isl_take isl_schedule *a, __isl_take isl_schedule *b)
976 gcc_assert (a || b);
978 if (!a)
979 return b;
981 if (!b)
982 return a;
984 return isl_schedule_sequence (a, b);
987 struct map_to_dimension_data {
988 int n;
989 isl_union_pw_multi_aff *res;
992 /* Create a function that maps the elements of SET to its N-th dimension and add
993 it to USER->res. */
995 static isl_stat
996 add_outer_projection (__isl_take isl_set *set, void *user)
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);
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);
1008 isl_set_free (set);
1009 return isl_stat_ok;
1012 /* Return SET in which all inner dimensions above N are removed. */
1014 static isl_multi_union_pw_aff *
1015 outer_projection_mupa (__isl_take isl_union_set *set, int n)
1017 gcc_assert (n >= 0);
1018 gcc_assert (set);
1019 gcc_assert (!isl_union_set_is_empty (set));
1021 isl_space *space = isl_union_set_get_space (set);
1022 isl_union_pw_multi_aff *pwaff = isl_union_pw_multi_aff_empty (space);
1024 struct map_to_dimension_data data = {n, pwaff};
1026 if (isl_union_set_foreach_set (set, &add_outer_projection, &data) < 0)
1027 data.res = isl_union_pw_multi_aff_free (data.res);
1029 isl_union_set_free (set);
1030 return isl_multi_union_pw_aff_from_union_pw_multi_aff (data.res);
1033 /* Embed SCHEDULE in the constraints of the LOOP domain. */
1035 static isl_schedule *
1036 add_loop_schedule (__isl_take isl_schedule *schedule, loop_p loop,
1037 scop_p scop)
1039 poly_bb_p pbb = outermost_pbb_in (loop, scop);
1040 isl_set *iterators = pbb->iterators;
1042 int empty = isl_set_is_empty (iterators);
1043 if (empty < 0 || empty)
1044 return empty < 0 ? isl_schedule_free (schedule) : schedule;
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))
1050 isl_union_set_free (domain);
1051 return schedule;
1054 isl_space *space = isl_set_get_space (iterators);
1055 int loop_index = isl_space_dim (space, isl_dim_set) - 1;
1057 loop_p ploop = pbb_loop (pbb);
1058 while (loop != ploop)
1060 --loop_index;
1061 ploop = loop_outer (ploop);
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);
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);
1079 /* Build schedule for the pbb at INDEX. */
1081 static isl_schedule *
1082 build_schedule_pbb (scop_p scop, int *index)
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);
1091 static isl_schedule *build_schedule_loop_nest (scop_p, int *, loop_p);
1093 /* Build the schedule of the loop containing the SCOP pbb at INDEX. */
1095 static isl_schedule *
1096 build_schedule_loop (scop_p scop, int *index)
1098 int max = scop->pbbs.length ();
1099 gcc_assert (*index < max);
1100 loop_p loop = loop_at (scop, index);
1102 isl_schedule *s = NULL;
1103 while (nested_in (loop_at (scop, index), loop))
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));
1110 if (*index == max)
1111 break;
1114 return add_loop_schedule (s, loop, scop);
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. */
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)
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;
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);
1141 bool a_pbb;
1142 while ((a_pbb = (outer == loop_at (scop, index)))
1143 || nested_in (loop_at (scop, index), outer))
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));
1150 if (*index == max)
1151 break;
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);
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. */
1164 static isl_schedule *
1165 build_schedule_loop_nest (scop_p scop, int *index, loop_p context_loop)
1167 gcc_assert (*index != (int) scop->pbbs.length ());
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);
1174 /* Build the schedule of the SCOP. */
1176 static void
1177 build_original_schedule (scop_p scop)
1179 int i = 0;
1180 int n = scop->pbbs.length ();
1181 while (i < n)
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);
1190 scop->original_schedule = add_in_sequence (scop->original_schedule, s);
1193 if (dump_file)
1195 fprintf (dump_file, "[sese-to-poly] original schedule:\n");
1196 print_isl_schedule (dump_file, scop->original_schedule);
1200 /* Builds the polyhedral representation for a SESE region. */
1202 bool
1203 build_poly_scop (scop_p scop)
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);
1208 build_scop_context (scop);
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);
1215 build_scop_drs (scop);
1216 build_original_schedule (scop);
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_printf (MSG_MISSED_OPTIMIZATION,
1223 "ISL error while building poly scop\n");
1225 return err == isl_error_none;
1227 #endif /* HAVE_isl */