Turn SECONDARY_MEMORY_NEEDED_MODE into a target hook
[official-gcc.git] / gcc / graphite-sese-to-poly.c
blob8ff9a22e1291660d6d4c22d15441db18405d9142
1 /* Conversion of SESE regions to Polyhedra.
2 Copyright (C) 2009-2017 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 /* Assigns to RES the value of the INTEGER_CST T. */
63 static inline void
64 tree_int_to_gmp (tree t, mpz_t res)
66 wi::to_mpz (t, res, TYPE_SIGN (TREE_TYPE (t)));
69 /* Return an isl identifier for the polyhedral basic block PBB. */
71 static isl_id *
72 isl_id_for_pbb (scop_p s, poly_bb_p pbb)
74 char name[14];
75 snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
76 return isl_id_alloc (s->isl_context, name, pbb);
79 static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space);
81 /* Extract an affine expression from the chain of recurrence E. */
83 static isl_pw_aff *
84 extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space)
86 isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space));
87 isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space));
88 isl_local_space *ls = isl_local_space_from_space (space);
89 unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)) - 1;
90 isl_aff *loop = isl_aff_set_coefficient_si
91 (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1);
92 isl_pw_aff *l = isl_pw_aff_from_aff (loop);
94 /* Before multiplying, make sure that the result is affine. */
95 gcc_assert (isl_pw_aff_is_cst (rhs)
96 || isl_pw_aff_is_cst (l));
98 return isl_pw_aff_add (lhs, isl_pw_aff_mul (rhs, l));
101 /* Extract an affine expression from the mult_expr E. */
103 static isl_pw_aff *
104 extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space)
106 isl_pw_aff *lhs = extract_affine (s, TREE_OPERAND (e, 0),
107 isl_space_copy (space));
108 isl_pw_aff *rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
110 if (!isl_pw_aff_is_cst (lhs)
111 && !isl_pw_aff_is_cst (rhs))
113 isl_pw_aff_free (lhs);
114 isl_pw_aff_free (rhs);
115 return NULL;
118 return isl_pw_aff_mul (lhs, rhs);
121 /* Return an isl identifier from the name of the ssa_name E. */
123 static isl_id *
124 isl_id_for_ssa_name (scop_p s, tree e)
126 char name1[14];
127 snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e));
128 return isl_id_alloc (s->isl_context, name1, e);
131 /* Return an isl identifier for the data reference DR. Data references and
132 scalar references get the same isl_id. They need to be comparable and are
133 distinguished through the first dimension, which contains the alias set or
134 SSA_NAME_VERSION number. */
136 static isl_id *
137 isl_id_for_dr (scop_p s)
139 return isl_id_alloc (s->isl_context, "", 0);
142 /* Extract an affine expression from the ssa_name E. */
144 static isl_pw_aff *
145 extract_affine_name (scop_p s, tree e, __isl_take isl_space *space)
147 isl_id *id = isl_id_for_ssa_name (s, e);
148 int dimension = isl_space_find_dim_by_id (space, isl_dim_param, id);
149 isl_id_free (id);
150 isl_set *dom = isl_set_universe (isl_space_copy (space));
151 isl_aff *aff = isl_aff_zero_on_domain (isl_local_space_from_space (space));
152 aff = isl_aff_add_coefficient_si (aff, isl_dim_param, dimension, 1);
153 return isl_pw_aff_alloc (dom, aff);
156 /* Convert WI to a isl_val with CTX. */
158 static __isl_give isl_val *
159 isl_val_int_from_wi (isl_ctx *ctx, const widest_int &wi)
161 if (wi::neg_p (wi, SIGNED))
163 widest_int mwi = -wi;
164 return isl_val_neg (isl_val_int_from_chunks (ctx, mwi.get_len (),
165 sizeof (HOST_WIDE_INT),
166 mwi.get_val ()));
168 return isl_val_int_from_chunks (ctx, wi.get_len (), sizeof (HOST_WIDE_INT),
169 wi.get_val ());
172 /* Extract an affine expression from the gmp constant G. */
174 static isl_pw_aff *
175 extract_affine_wi (const widest_int &g, __isl_take isl_space *space)
177 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
178 isl_aff *aff = isl_aff_zero_on_domain (ls);
179 isl_set *dom = isl_set_universe (space);
180 isl_ctx *ct = isl_aff_get_ctx (aff);
181 isl_val *v = isl_val_int_from_wi (ct, g);
182 aff = isl_aff_add_constant_val (aff, v);
184 return isl_pw_aff_alloc (dom, aff);
187 /* Extract an affine expression from the integer_cst E. */
189 static isl_pw_aff *
190 extract_affine_int (tree e, __isl_take isl_space *space)
192 isl_pw_aff *res = extract_affine_wi (wi::to_widest (e), space);
193 return res;
196 /* Compute pwaff mod 2^width. */
198 static isl_pw_aff *
199 wrap (isl_pw_aff *pwaff, unsigned width)
201 isl_val *mod;
203 mod = isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff), width);
204 mod = isl_val_2exp (mod);
205 pwaff = isl_pw_aff_mod_val (pwaff, mod);
207 return pwaff;
210 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
211 Otherwise returns -1. */
213 static inline int
214 parameter_index_in_region_1 (tree name, sese_info_p region)
216 int i;
217 tree p;
219 gcc_assert (TREE_CODE (name) == SSA_NAME);
221 FOR_EACH_VEC_ELT (region->params, i, p)
222 if (p == name)
223 return i;
225 return -1;
228 /* Extract an affine expression from the tree E in the scop S. */
230 static isl_pw_aff *
231 extract_affine (scop_p s, tree e, __isl_take isl_space *space)
233 isl_pw_aff *lhs, *rhs, *res;
235 if (e == chrec_dont_know) {
236 isl_space_free (space);
237 return NULL;
240 switch (TREE_CODE (e))
242 case POLYNOMIAL_CHREC:
243 res = extract_affine_chrec (s, e, space);
244 break;
246 case MULT_EXPR:
247 res = extract_affine_mul (s, e, space);
248 break;
250 case PLUS_EXPR:
251 case POINTER_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 NEGATE_EXPR:
264 case BIT_NOT_EXPR:
265 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
266 rhs = extract_affine (s, integer_minus_one_node, space);
267 res = isl_pw_aff_mul (lhs, rhs);
268 break;
270 case SSA_NAME:
271 gcc_assert (-1 != parameter_index_in_region_1 (e, s->scop_info)
272 || defined_in_sese_p (e, s->scop_info->region));
273 res = extract_affine_name (s, e, space);
274 break;
276 case INTEGER_CST:
277 res = extract_affine_int (e, space);
278 /* No need to wrap a single integer. */
279 return res;
281 CASE_CONVERT:
282 case NON_LVALUE_EXPR:
283 res = extract_affine (s, TREE_OPERAND (e, 0), space);
284 break;
286 default:
287 gcc_unreachable ();
288 break;
291 tree type = TREE_TYPE (e);
292 if (TYPE_UNSIGNED (type))
293 res = wrap (res, TYPE_PRECISION (type));
295 return res;
298 /* Returns a linear expression for tree T evaluated in PBB. */
300 static isl_pw_aff *
301 create_pw_aff_from_tree (poly_bb_p pbb, loop_p loop, tree t)
303 scop_p scop = PBB_SCOP (pbb);
305 t = scalar_evolution_in_region (scop->scop_info->region, loop, t);
307 gcc_assert (!chrec_contains_undetermined (t));
308 gcc_assert (!automatically_generated_chrec_p (t));
310 return extract_affine (scop, t, isl_set_get_space (pbb->domain));
313 /* Add conditional statement STMT to pbb. CODE is used as the comparison
314 operator. This allows us to invert the condition or to handle
315 inequalities. */
317 static void
318 add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code)
320 loop_p loop = gimple_bb (stmt)->loop_father;
321 isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_lhs (stmt));
322 isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_rhs (stmt));
324 isl_set *cond;
325 switch (code)
327 case LT_EXPR:
328 cond = isl_pw_aff_lt_set (lhs, rhs);
329 break;
331 case GT_EXPR:
332 cond = isl_pw_aff_gt_set (lhs, rhs);
333 break;
335 case LE_EXPR:
336 cond = isl_pw_aff_le_set (lhs, rhs);
337 break;
339 case GE_EXPR:
340 cond = isl_pw_aff_ge_set (lhs, rhs);
341 break;
343 case EQ_EXPR:
344 cond = isl_pw_aff_eq_set (lhs, rhs);
345 break;
347 case NE_EXPR:
348 cond = isl_pw_aff_ne_set (lhs, rhs);
349 break;
351 default:
352 gcc_unreachable ();
355 cond = isl_set_coalesce (cond);
356 cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain));
357 pbb->domain = isl_set_coalesce (isl_set_intersect (pbb->domain, cond));
360 /* Add conditions to the domain of PBB. */
362 static void
363 add_conditions_to_domain (poly_bb_p pbb)
365 unsigned int i;
366 gimple *stmt;
367 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
369 if (GBB_CONDITIONS (gbb).is_empty ())
370 return;
372 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
373 switch (gimple_code (stmt))
375 case GIMPLE_COND:
377 /* Don't constrain on anything else than INTEGER_TYPE. */
378 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt))) != INTEGER_TYPE)
379 break;
381 gcond *cond_stmt = as_a <gcond *> (stmt);
382 enum tree_code code = gimple_cond_code (cond_stmt);
384 /* The conditions for ELSE-branches are inverted. */
385 if (!GBB_CONDITION_CASES (gbb)[i])
386 code = invert_tree_comparison (code, false);
388 add_condition_to_pbb (pbb, cond_stmt, code);
389 break;
392 default:
393 gcc_unreachable ();
394 break;
398 /* Add constraints on the possible values of parameter P from the type
399 of P. */
401 static void
402 add_param_constraints (scop_p scop, graphite_dim_t p)
404 tree parameter = scop->scop_info->params[p];
405 tree type = TREE_TYPE (parameter);
406 tree lb = NULL_TREE;
407 tree ub = NULL_TREE;
409 if (POINTER_TYPE_P (type) || !TYPE_MIN_VALUE (type))
410 lb = lower_bound_in_type (type, type);
411 else
412 lb = TYPE_MIN_VALUE (type);
414 if (POINTER_TYPE_P (type) || !TYPE_MAX_VALUE (type))
415 ub = upper_bound_in_type (type, type);
416 else
417 ub = TYPE_MAX_VALUE (type);
419 if (lb)
421 isl_space *space = isl_set_get_space (scop->param_context);
422 isl_constraint *c;
423 isl_val *v;
425 c = isl_inequality_alloc (isl_local_space_from_space (space));
426 v = isl_val_int_from_wi (scop->isl_context, wi::to_widest (lb));
427 v = isl_val_neg (v);
428 c = isl_constraint_set_constant_val (c, v);
429 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, 1);
431 scop->param_context = isl_set_coalesce
432 (isl_set_add_constraint (scop->param_context, c));
435 if (ub)
437 isl_space *space = isl_set_get_space (scop->param_context);
438 isl_constraint *c;
439 isl_val *v;
441 c = isl_inequality_alloc (isl_local_space_from_space (space));
443 v = isl_val_int_from_wi (scop->isl_context, wi::to_widest (ub));
444 c = isl_constraint_set_constant_val (c, v);
445 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, -1);
447 scop->param_context = isl_set_coalesce
448 (isl_set_add_constraint (scop->param_context, c));
452 /* Add a constrain to the ACCESSES polyhedron for the alias set of
453 data reference DR. ACCESSP_NB_DIMS is the dimension of the
454 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
455 domain. */
457 static isl_map *
458 pdr_add_alias_set (isl_map *acc, dr_info &dri)
460 isl_constraint *c = isl_equality_alloc
461 (isl_local_space_from_space (isl_map_get_space (acc)));
462 /* Positive numbers for all alias sets. */
463 c = isl_constraint_set_constant_si (c, -dri.alias_set);
464 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
466 return isl_map_add_constraint (acc, c);
469 /* Add a constrain to the ACCESSES polyhedron for the alias set of
470 data reference DR. ACCESSP_NB_DIMS is the dimension of the
471 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
472 domain. */
474 static isl_map *
475 add_scalar_version_numbers (isl_map *acc, tree var)
477 isl_constraint *c = isl_equality_alloc
478 (isl_local_space_from_space (isl_map_get_space (acc)));
479 int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP);
480 /* Each scalar variables has a unique alias set number starting from
481 max_arrays. */
482 c = isl_constraint_set_constant_si (c, -max_arrays - SSA_NAME_VERSION (var));
483 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
485 return isl_map_add_constraint (acc, c);
488 /* Assign the affine expression INDEX to the output dimension POS of
489 MAP and return the result. */
491 static isl_map *
492 set_index (isl_map *map, int pos, isl_pw_aff *index)
494 isl_map *index_map;
495 int len = isl_map_dim (map, isl_dim_out);
496 isl_id *id;
498 index_map = isl_map_from_pw_aff (index);
499 index_map = isl_map_insert_dims (index_map, isl_dim_out, 0, pos);
500 index_map = isl_map_add_dims (index_map, isl_dim_out, len - pos - 1);
502 id = isl_map_get_tuple_id (map, isl_dim_out);
503 index_map = isl_map_set_tuple_id (index_map, isl_dim_out, id);
504 id = isl_map_get_tuple_id (map, isl_dim_in);
505 index_map = isl_map_set_tuple_id (index_map, isl_dim_in, id);
507 return isl_map_intersect (map, index_map);
510 /* Add to ACCESSES polyhedron equalities defining the access functions
511 to the memory. ACCESSP_NB_DIMS is the dimension of the ACCESSES
512 polyhedron, DOM_NB_DIMS is the dimension of the iteration domain.
513 PBB is the poly_bb_p that contains the data reference DR. */
515 static isl_map *
516 pdr_add_memory_accesses (isl_map *acc, dr_info &dri)
518 data_reference_p dr = dri.dr;
519 poly_bb_p pbb = dri.pbb;
520 int i, nb_subscripts = DR_NUM_DIMENSIONS (dr);
521 scop_p scop = PBB_SCOP (pbb);
523 for (i = 0; i < nb_subscripts; i++)
525 isl_pw_aff *aff;
526 tree afn = DR_ACCESS_FN (dr, i);
528 aff = extract_affine (scop, afn,
529 isl_space_domain (isl_map_get_space (acc)));
530 acc = set_index (acc, nb_subscripts - i , aff);
533 return isl_map_coalesce (acc);
536 /* Return true when the LOW and HIGH bounds of an array reference REF are valid
537 to extract constraints on accessed elements of the array. Returning false is
538 the conservative answer. */
540 static bool
541 bounds_are_valid (tree ref, tree low, tree high)
543 if (!high)
544 return false;
546 if (!tree_fits_shwi_p (low)
547 || !tree_fits_shwi_p (high))
548 return false;
550 /* 1-element arrays at end of structures may extend over
551 their declared size. */
552 if (array_at_struct_end_p (ref)
553 && operand_equal_p (low, high, 0))
554 return false;
556 /* Fortran has some arrays where high bound is -1 and low is 0. */
557 if (integer_onep (fold_build2 (LT_EXPR, boolean_type_node, high, low)))
558 return false;
560 return true;
563 /* Add constrains representing the size of the accessed data to the
564 ACCESSES polyhedron. ACCESSP_NB_DIMS is the dimension of the
565 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
566 domain. */
568 static isl_set *
569 pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop,
570 data_reference_p dr)
572 tree ref = DR_REF (dr);
574 int nb_subscripts = DR_NUM_DIMENSIONS (dr);
575 for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0))
577 if (TREE_CODE (ref) != ARRAY_REF)
578 return subscript_sizes;
580 tree low = array_ref_low_bound (ref);
581 tree high = array_ref_up_bound (ref);
583 if (!bounds_are_valid (ref, low, high))
584 continue;
586 isl_space *space = isl_set_get_space (subscript_sizes);
587 isl_pw_aff *lb = extract_affine_int (low, isl_space_copy (space));
588 isl_pw_aff *ub = extract_affine_int (high, isl_space_copy (space));
590 /* high >= 0 */
591 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub));
592 valid = isl_set_project_out (valid, isl_dim_set, 0,
593 isl_set_dim (valid, isl_dim_set));
594 scop->param_context = isl_set_coalesce
595 (isl_set_intersect (scop->param_context, valid));
597 isl_aff *aff
598 = isl_aff_zero_on_domain (isl_local_space_from_space (space));
599 aff = isl_aff_add_coefficient_si (aff, isl_dim_in, i + 1, 1);
600 isl_set *univ
601 = isl_set_universe (isl_space_domain (isl_aff_get_space (aff)));
602 isl_pw_aff *index = isl_pw_aff_alloc (univ, aff);
604 isl_id *id = isl_set_get_tuple_id (subscript_sizes);
605 lb = isl_pw_aff_set_tuple_id (lb, isl_dim_in, isl_id_copy (id));
606 ub = isl_pw_aff_set_tuple_id (ub, isl_dim_in, id);
608 /* low <= sub_i <= high */
609 isl_set *lbs = isl_pw_aff_ge_set (isl_pw_aff_copy (index), lb);
610 isl_set *ubs = isl_pw_aff_le_set (index, ub);
611 subscript_sizes = isl_set_intersect (subscript_sizes, lbs);
612 subscript_sizes = isl_set_intersect (subscript_sizes, ubs);
615 return isl_set_coalesce (subscript_sizes);
618 /* Build data accesses for DRI. */
620 static void
621 build_poly_dr (dr_info &dri)
623 isl_map *acc;
624 isl_set *subscript_sizes;
625 poly_bb_p pbb = dri.pbb;
626 data_reference_p dr = dri.dr;
627 scop_p scop = PBB_SCOP (pbb);
628 isl_id *id = isl_id_for_dr (scop);
631 isl_space *dc = isl_set_get_space (pbb->domain);
632 int nb_out = 1 + DR_NUM_DIMENSIONS (dr);
633 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
634 isl_dim_out, nb_out);
636 acc = isl_map_universe (space);
637 acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id));
640 acc = pdr_add_alias_set (acc, dri);
641 acc = pdr_add_memory_accesses (acc, dri);
644 int nb = 1 + DR_NUM_DIMENSIONS (dr);
645 isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb);
647 space = isl_space_set_tuple_id (space, isl_dim_set, id);
648 subscript_sizes = isl_set_nat_universe (space);
649 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
650 dri.alias_set);
651 subscript_sizes = pdr_add_data_dimensions (subscript_sizes, scop, dr);
654 new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE,
655 acc, subscript_sizes);
658 static void
659 build_poly_sr_1 (poly_bb_p pbb, gimple *stmt, tree var, enum poly_dr_type kind,
660 isl_map *acc, isl_set *subscript_sizes)
662 int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP);
663 /* Each scalar variables has a unique alias set number starting from
664 max_arrays. */
665 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
666 max_arrays + SSA_NAME_VERSION (var));
668 new_poly_dr (pbb, stmt, kind, add_scalar_version_numbers (acc, var),
669 subscript_sizes);
672 /* Record all cross basic block scalar variables in PBB. */
674 static void
675 build_poly_sr (poly_bb_p pbb)
677 scop_p scop = PBB_SCOP (pbb);
678 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
679 vec<scalar_use> &reads = gbb->read_scalar_refs;
680 vec<tree> &writes = gbb->write_scalar_refs;
682 isl_space *dc = isl_set_get_space (pbb->domain);
683 int nb_out = 1;
684 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
685 isl_dim_out, nb_out);
686 isl_id *id = isl_id_for_dr (scop);
687 space = isl_space_set_tuple_id (space, isl_dim_set, isl_id_copy (id));
688 isl_map *acc = isl_map_universe (isl_space_copy (space));
689 acc = isl_map_set_tuple_id (acc, isl_dim_out, id);
690 isl_set *subscript_sizes = isl_set_nat_universe (space);
692 int i;
693 tree var;
694 FOR_EACH_VEC_ELT (writes, i, var)
695 build_poly_sr_1 (pbb, SSA_NAME_DEF_STMT (var), var, PDR_WRITE,
696 isl_map_copy (acc), isl_set_copy (subscript_sizes));
698 scalar_use *use;
699 FOR_EACH_VEC_ELT (reads, i, use)
700 build_poly_sr_1 (pbb, use->first, use->second, PDR_READ, isl_map_copy (acc),
701 isl_set_copy (subscript_sizes));
703 isl_map_free (acc);
704 isl_set_free (subscript_sizes);
707 /* Build data references in SCOP. */
709 static void
710 build_scop_drs (scop_p scop)
712 int i;
713 dr_info *dri;
714 FOR_EACH_VEC_ELT (scop->drs, i, dri)
715 build_poly_dr (*dri);
717 poly_bb_p pbb;
718 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
719 build_poly_sr (pbb);
722 /* Add to the iteration DOMAIN one extra dimension for LOOP->num. */
724 static isl_set *
725 add_iter_domain_dimension (__isl_take isl_set *domain, loop_p loop, scop_p scop)
727 int loop_index = isl_set_dim (domain, isl_dim_set);
728 domain = isl_set_add_dims (domain, isl_dim_set, 1);
729 char name[50];
730 snprintf (name, sizeof(name), "i%d", loop->num);
731 isl_id *label = isl_id_alloc (scop->isl_context, name, NULL);
732 return isl_set_set_dim_id (domain, isl_dim_set, loop_index, label);
735 /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */
737 static isl_set *
738 add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop,
739 loop_p context)
741 if (loop == context)
742 return domain;
743 const sese_l &region = scop->scop_info->region;
744 if (!loop_in_sese_p (loop, region))
745 return domain;
747 /* Recursion all the way up to the context loop. */
748 domain = add_loop_constraints (scop, domain, loop_outer (loop), context);
750 /* Then, build constraints over the loop in post-order: outer to inner. */
752 int loop_index = isl_set_dim (domain, isl_dim_set);
753 if (dump_file)
754 fprintf (dump_file, "[sese-to-poly] adding one extra dimension to the "
755 "domain for loop_%d.\n", loop->num);
756 domain = add_iter_domain_dimension (domain, loop, scop);
757 isl_space *space = isl_set_get_space (domain);
759 /* 0 <= loop_i */
760 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
761 isl_constraint *c = isl_inequality_alloc (ls);
762 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, 1);
763 if (dump_file)
765 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
766 print_isl_constraint (dump_file, c);
768 domain = isl_set_add_constraint (domain, c);
770 tree nb_iters = number_of_latch_executions (loop);
771 if (TREE_CODE (nb_iters) == INTEGER_CST)
773 /* loop_i <= cst_nb_iters */
774 isl_local_space *ls = isl_local_space_from_space (space);
775 isl_constraint *c = isl_inequality_alloc (ls);
776 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
777 isl_val *v
778 = isl_val_int_from_wi (scop->isl_context, wi::to_widest (nb_iters));
779 c = isl_constraint_set_constant_val (c, v);
780 return isl_set_add_constraint (domain, c);
782 /* loop_i <= expr_nb_iters */
783 gcc_assert (!chrec_contains_undetermined (nb_iters));
784 nb_iters = scalar_evolution_in_region (region, loop, nb_iters);
785 gcc_assert (!chrec_contains_undetermined (nb_iters));
787 isl_pw_aff *aff_nb_iters = extract_affine (scop, nb_iters,
788 isl_space_copy (space));
789 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters));
790 valid = isl_set_project_out (valid, isl_dim_set, 0,
791 isl_set_dim (valid, isl_dim_set));
793 if (valid)
794 scop->param_context = isl_set_intersect (scop->param_context, valid);
796 ls = isl_local_space_from_space (isl_space_copy (space));
797 isl_aff *loop_i = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls),
798 isl_dim_in, loop_index, 1);
799 isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i),
800 isl_pw_aff_copy (aff_nb_iters));
801 if (dump_file)
803 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
804 print_isl_set (dump_file, le);
806 domain = isl_set_intersect (domain, le);
808 widest_int nit;
809 if (!max_stmt_executions (loop, &nit))
811 isl_pw_aff_free (aff_nb_iters);
812 isl_space_free (space);
813 return domain;
816 /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we
817 do not know whether the loop executes at least once. */
818 --nit;
820 isl_pw_aff *approx = extract_affine_wi (nit, isl_space_copy (space));
821 isl_set *x = isl_pw_aff_ge_set (approx, aff_nb_iters);
822 x = isl_set_project_out (x, isl_dim_set, 0,
823 isl_set_dim (x, isl_dim_set));
824 scop->param_context = isl_set_intersect (scop->param_context, x);
826 ls = isl_local_space_from_space (space);
827 c = isl_inequality_alloc (ls);
828 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
829 isl_val *v = isl_val_int_from_wi (scop->isl_context, nit);
830 c = isl_constraint_set_constant_val (c, v);
832 if (dump_file)
834 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
835 print_isl_constraint (dump_file, c);
838 return isl_set_add_constraint (domain, c);
841 /* Builds the original iteration domains for each pbb in the SCOP. */
843 static int
844 build_iteration_domains (scop_p scop, __isl_keep isl_set *context,
845 int index, loop_p context_loop)
847 loop_p current = pbb_loop (scop->pbbs[index]);
848 isl_set *domain = isl_set_copy (context);
849 domain = add_loop_constraints (scop, domain, current, context_loop);
850 const sese_l &region = scop->scop_info->region;
852 int i;
853 poly_bb_p pbb;
854 FOR_EACH_VEC_ELT_FROM (scop->pbbs, i, pbb, index)
856 loop_p loop = pbb_loop (pbb);
857 if (current == loop)
859 pbb->iterators = isl_set_copy (domain);
860 pbb->domain = isl_set_copy (domain);
861 pbb->domain = isl_set_set_tuple_id (pbb->domain,
862 isl_id_for_pbb (scop, pbb));
863 add_conditions_to_domain (pbb);
865 if (dump_file)
867 fprintf (dump_file, "[sese-to-poly] set pbb_%d->domain: ",
868 pbb_index (pbb));
869 print_isl_set (dump_file, domain);
871 continue;
874 while (loop_in_sese_p (loop, region)
875 && current != loop)
876 loop = loop_outer (loop);
878 if (current != loop)
880 /* A statement in a different loop nest than CURRENT loop. */
881 isl_set_free (domain);
882 return i;
885 /* A statement nested in the CURRENT loop. */
886 i = build_iteration_domains (scop, domain, i, current);
887 i--;
890 isl_set_free (domain);
891 return i;
894 /* Assign dimension for each parameter in SCOP and add constraints for the
895 parameters. */
897 static void
898 build_scop_context (scop_p scop)
900 sese_info_p region = scop->scop_info;
901 unsigned nbp = sese_nb_params (region);
902 isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0);
904 unsigned i;
905 tree e;
906 FOR_EACH_VEC_ELT (region->params, i, e)
907 space = isl_space_set_dim_id (space, isl_dim_param, i,
908 isl_id_for_ssa_name (scop, e));
910 scop->param_context = isl_set_universe (space);
912 graphite_dim_t p;
913 for (p = 0; p < nbp; p++)
914 add_param_constraints (scop, p);
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_space *space = isl_set_get_space (iterators);
1047 int loop_index = isl_space_dim (space, isl_dim_set) - 1;
1049 loop_p ploop = pbb_loop (pbb);
1050 while (loop != ploop)
1052 --loop_index;
1053 ploop = loop_outer (ploop);
1056 isl_local_space *ls = isl_local_space_from_space (space);
1057 isl_aff *aff = isl_aff_var_on_domain (ls, isl_dim_set, loop_index);
1058 isl_multi_aff *prefix = isl_multi_aff_from_aff (aff);
1059 char name[50];
1060 snprintf (name, sizeof(name), "L_%d", loop->num);
1061 isl_id *label = isl_id_alloc (isl_schedule_get_ctx (schedule),
1062 name, NULL);
1063 prefix = isl_multi_aff_set_tuple_id (prefix, isl_dim_out, label);
1065 int n = isl_multi_aff_dim (prefix, isl_dim_in);
1066 isl_union_set *domain = isl_schedule_get_domain (schedule);
1067 isl_multi_union_pw_aff *mupa = outer_projection_mupa (domain, n);
1068 mupa = isl_multi_union_pw_aff_apply_multi_aff (mupa, prefix);
1069 return isl_schedule_insert_partial_schedule (schedule, mupa);
1072 /* Build schedule for the pbb at INDEX. */
1074 static isl_schedule *
1075 build_schedule_pbb (scop_p scop, int *index)
1077 poly_bb_p pbb = scop->pbbs[*index];
1078 ++*index;
1079 isl_set *domain = isl_set_copy (pbb->domain);
1080 isl_union_set *ud = isl_union_set_from_set (domain);
1081 return isl_schedule_from_domain (ud);
1084 static isl_schedule *build_schedule_loop_nest (scop_p, int *, loop_p);
1086 /* Build the schedule of the loop containing the SCOP pbb at INDEX. */
1088 static isl_schedule *
1089 build_schedule_loop (scop_p scop, int *index)
1091 int max = scop->pbbs.length ();
1092 gcc_assert (*index < max);
1093 loop_p loop = loop_at (scop, index);
1095 isl_schedule *s = NULL;
1096 while (nested_in (loop_at (scop, index), loop))
1098 if (loop == loop_at (scop, index))
1099 s = add_in_sequence (s, build_schedule_pbb (scop, index));
1100 else
1101 s = add_in_sequence (s, build_schedule_loop_nest (scop, index, loop));
1103 if (*index == max)
1104 break;
1107 return add_loop_schedule (s, loop, scop);
1110 /* S is the schedule of the loop LOOP. Embed the schedule S in all outer loops.
1111 When CONTEXT_LOOP is null, embed the schedule in all loops contained in the
1112 SCOP surrounding LOOP. When CONTEXT_LOOP is non null, only embed S in the
1113 maximal loop nest contained within CONTEXT_LOOP. */
1115 static isl_schedule *
1116 embed_in_surrounding_loops (__isl_take isl_schedule *s, scop_p scop,
1117 loop_p loop, int *index, loop_p context_loop)
1119 loop_p outer = loop_outer (loop);
1120 sese_l region = scop->scop_info->region;
1121 if (context_loop == outer
1122 || !loop_in_sese_p (outer, region))
1123 return s;
1125 int max = scop->pbbs.length ();
1126 if (*index == max
1127 || (context_loop && !nested_in (loop_at (scop, index), context_loop))
1128 || (!context_loop
1129 && !loop_in_sese_p (find_common_loop (outer, loop_at (scop, index)),
1130 region)))
1131 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop),
1132 scop, outer, index, context_loop);
1134 bool a_pbb;
1135 while ((a_pbb = (outer == loop_at (scop, index)))
1136 || nested_in (loop_at (scop, index), outer))
1138 if (a_pbb)
1139 s = add_in_sequence (s, build_schedule_pbb (scop, index));
1140 else
1141 s = add_in_sequence (s, build_schedule_loop (scop, index));
1143 if (*index == max)
1144 break;
1147 /* We reached the end of the OUTER loop: embed S in OUTER. */
1148 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), scop,
1149 outer, index, context_loop);
1152 /* Build schedule for the full loop nest containing the pbb at INDEX. When
1153 CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP
1154 surrounding the pbb. When CONTEXT_LOOP is non null, only build the maximal loop
1155 nest contained within CONTEXT_LOOP. */
1157 static isl_schedule *
1158 build_schedule_loop_nest (scop_p scop, int *index, loop_p context_loop)
1160 gcc_assert (*index != (int) scop->pbbs.length ());
1162 loop_p loop = loop_at (scop, index);
1163 isl_schedule *s = build_schedule_loop (scop, index);
1164 return embed_in_surrounding_loops (s, scop, loop, index, context_loop);
1167 /* Build the schedule of the SCOP. */
1169 static bool
1170 build_original_schedule (scop_p scop)
1172 int i = 0;
1173 int n = scop->pbbs.length ();
1174 while (i < n)
1176 poly_bb_p pbb = scop->pbbs[i];
1177 isl_schedule *s = NULL;
1178 if (!loop_in_sese_p (pbb_loop (pbb), scop->scop_info->region))
1179 s = build_schedule_pbb (scop, &i);
1180 else
1181 s = build_schedule_loop_nest (scop, &i, NULL);
1183 scop->original_schedule = add_in_sequence (scop->original_schedule, s);
1186 if (dump_file)
1188 fprintf (dump_file, "[sese-to-poly] original schedule:\n");
1189 print_isl_schedule (dump_file, scop->original_schedule);
1191 if (!scop->original_schedule)
1192 return false;
1193 return true;
1196 /* Builds the polyhedral representation for a SESE region. */
1198 bool
1199 build_poly_scop (scop_p scop)
1201 build_scop_context (scop);
1203 unsigned i = 0;
1204 unsigned n = scop->pbbs.length ();
1205 while (i < n)
1206 i = build_iteration_domains (scop, scop->param_context, i, NULL);
1208 build_scop_drs (scop);
1209 build_original_schedule (scop);
1210 return true;
1212 #endif /* HAVE_isl */