PR c++/67273
[official-gcc.git] / gcc / graphite-sese-to-poly.c
blob7583cc92a988aff476060edf4f0675ca6931b186
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>
58 #include <isl/val_gmp.h>
60 #include "graphite.h"
62 /* Assigns to RES the value of the INTEGER_CST T. */
64 static inline void
65 tree_int_to_gmp (tree t, mpz_t res)
67 wi::to_mpz (t, res, TYPE_SIGN (TREE_TYPE (t)));
70 /* Return an isl identifier for the polyhedral basic block PBB. */
72 static isl_id *
73 isl_id_for_pbb (scop_p s, poly_bb_p pbb)
75 char name[14];
76 snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
77 return isl_id_alloc (s->isl_context, name, pbb);
80 #ifndef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
81 /* Converts the STATIC_SCHEDULE of PBB into a scattering polyhedron.
82 We generate SCATTERING_DIMENSIONS scattering dimensions.
84 The scattering polyhedron consists of these dimensions: scattering,
85 loop_iterators, parameters.
87 Example:
89 | scattering_dimensions = 5
90 | nb_iterators = 1
91 | scop_nb_params = 2
93 | Schedule:
94 | i
95 | 4 5
97 | Scattering polyhedron:
99 | scattering: {s1, s2, s3, s4, s5}
100 | loop_iterators: {i}
101 | parameters: {p1, p2}
103 | s1 s2 s3 s4 s5 i p1 p2 1
104 | 1 0 0 0 0 0 0 0 -4 = 0
105 | 0 1 0 0 0 -1 0 0 0 = 0
106 | 0 0 1 0 0 0 0 0 -5 = 0 */
108 static void
109 build_pbb_scattering_polyhedrons (isl_aff *static_sched,
110 poly_bb_p pbb)
112 isl_val *val;
114 int scattering_dimensions = isl_set_dim (pbb->domain, isl_dim_set) * 2 + 1;
116 isl_space *dc = isl_set_get_space (pbb->domain);
117 isl_space *dm = isl_space_add_dims (isl_space_from_domain (dc),
118 isl_dim_out, scattering_dimensions);
119 pbb->schedule = isl_map_universe (dm);
121 for (int i = 0; i < scattering_dimensions; i++)
123 /* Textual order inside this loop. */
124 if ((i % 2) == 0)
126 isl_constraint *c = isl_equality_alloc
127 (isl_local_space_from_space (isl_map_get_space (pbb->schedule)));
129 val = isl_aff_get_coefficient_val (static_sched, isl_dim_in, i / 2);
130 gcc_assert (val && isl_val_is_int (val));
132 val = isl_val_neg (val);
133 c = isl_constraint_set_constant_val (c, val);
134 c = isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1);
135 pbb->schedule = isl_map_add_constraint (pbb->schedule, c);
138 /* Iterations of this loop. */
139 else /* if ((i % 2) == 1) */
141 int loop = (i - 1) / 2;
142 pbb->schedule = isl_map_equate (pbb->schedule, isl_dim_in, loop,
143 isl_dim_out, i);
147 /* Simplify the original schedule. */
148 pbb->schedule = isl_map_coalesce (pbb->schedule);
150 /* At the beginning, set the transformed schedule to the original. */
151 pbb->transformed = isl_map_copy (pbb->schedule);
154 /* Build for BB the static schedule.
156 The static schedule is a Dewey numbering of the abstract syntax
157 tree: http://en.wikipedia.org/wiki/Dewey_Decimal_Classification
159 The following example informally defines the static schedule:
162 for (i: ...)
164 for (j: ...)
170 for (k: ...)
178 Static schedules for A to F:
180 DEPTH
181 0 1 2
183 B 1 0 0
184 C 1 0 1
185 D 1 1 0
186 E 1 1 1
190 static void
191 build_scop_scattering (scop_p scop)
193 gimple_poly_bb_p previous_gbb = NULL;
194 isl_space *dc = isl_set_get_space (scop->param_context);
195 isl_aff *static_sched;
197 dc = isl_space_add_dims (dc, isl_dim_set, number_of_loops (cfun));
198 static_sched = isl_aff_zero_on_domain (isl_local_space_from_space (dc));
200 /* We have to start schedules at 0 on the first component and
201 because we cannot compare_prefix_loops against a previous loop,
202 prefix will be equal to zero, and that index will be
203 incremented before copying. */
204 static_sched = isl_aff_add_coefficient_si (static_sched, isl_dim_in, 0, -1);
206 int i;
207 poly_bb_p pbb;
208 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
210 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
211 int prefix = 0;
213 if (previous_gbb)
214 prefix = nb_common_loops (scop->scop_info->region, previous_gbb, gbb);
216 previous_gbb = gbb;
218 static_sched = isl_aff_add_coefficient_si (static_sched, isl_dim_in,
219 prefix, 1);
220 build_pbb_scattering_polyhedrons (static_sched, pbb);
223 isl_aff_free (static_sched);
225 #endif
227 static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space);
229 /* Extract an affine expression from the chain of recurrence E. */
231 static isl_pw_aff *
232 extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space)
234 isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space));
235 isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space));
236 isl_local_space *ls = isl_local_space_from_space (space);
237 unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)) - 1;
238 isl_aff *loop = isl_aff_set_coefficient_si
239 (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1);
240 isl_pw_aff *l = isl_pw_aff_from_aff (loop);
242 /* Before multiplying, make sure that the result is affine. */
243 gcc_assert (isl_pw_aff_is_cst (rhs)
244 || isl_pw_aff_is_cst (l));
246 return isl_pw_aff_add (lhs, isl_pw_aff_mul (rhs, l));
249 /* Extract an affine expression from the mult_expr E. */
251 static isl_pw_aff *
252 extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space)
254 isl_pw_aff *lhs = extract_affine (s, TREE_OPERAND (e, 0),
255 isl_space_copy (space));
256 isl_pw_aff *rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
258 if (!isl_pw_aff_is_cst (lhs)
259 && !isl_pw_aff_is_cst (rhs))
261 isl_pw_aff_free (lhs);
262 isl_pw_aff_free (rhs);
263 return NULL;
266 return isl_pw_aff_mul (lhs, rhs);
269 /* Return an isl identifier from the name of the ssa_name E. */
271 static isl_id *
272 isl_id_for_ssa_name (scop_p s, tree e)
274 char name1[14];
275 snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e));
276 return isl_id_alloc (s->isl_context, name1, e);
279 /* Return an isl identifier for the data reference DR. Data references and
280 scalar references get the same isl_id. They need to be comparable and are
281 distinguished through the first dimension, which contains the alias set or
282 SSA_NAME_VERSION number. */
284 static isl_id *
285 isl_id_for_dr (scop_p s)
287 return isl_id_alloc (s->isl_context, "", 0);
290 /* Extract an affine expression from the ssa_name E. */
292 static isl_pw_aff *
293 extract_affine_name (scop_p s, tree e, __isl_take isl_space *space)
295 isl_id *id = isl_id_for_ssa_name (s, e);
296 int dimension = isl_space_find_dim_by_id (space, isl_dim_param, id);
297 isl_id_free (id);
298 isl_set *dom = isl_set_universe (isl_space_copy (space));
299 isl_aff *aff = isl_aff_zero_on_domain (isl_local_space_from_space (space));
300 aff = isl_aff_add_coefficient_si (aff, isl_dim_param, dimension, 1);
301 return isl_pw_aff_alloc (dom, aff);
304 /* Extract an affine expression from the gmp constant G. */
306 static isl_pw_aff *
307 extract_affine_gmp (mpz_t g, __isl_take isl_space *space)
309 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
310 isl_aff *aff = isl_aff_zero_on_domain (ls);
311 isl_set *dom = isl_set_universe (space);
312 isl_ctx *ct = isl_aff_get_ctx (aff);
313 isl_val *v = isl_val_int_from_gmp (ct, g);
314 aff = isl_aff_add_constant_val (aff, v);
316 return isl_pw_aff_alloc (dom, aff);
319 /* Extract an affine expression from the integer_cst E. */
321 static isl_pw_aff *
322 extract_affine_int (tree e, __isl_take isl_space *space)
324 mpz_t g;
326 mpz_init (g);
327 tree_int_to_gmp (e, g);
328 isl_pw_aff *res = extract_affine_gmp (g, space);
329 mpz_clear (g);
331 return res;
334 /* Compute pwaff mod 2^width. */
336 static isl_pw_aff *
337 wrap (isl_pw_aff *pwaff, unsigned width)
339 isl_val *mod;
341 mod = isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff), width);
342 mod = isl_val_2exp (mod);
343 pwaff = isl_pw_aff_mod_val (pwaff, mod);
345 return pwaff;
348 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
349 Otherwise returns -1. */
351 static inline int
352 parameter_index_in_region_1 (tree name, sese_info_p region)
354 int i;
355 tree p;
357 gcc_assert (TREE_CODE (name) == SSA_NAME);
359 FOR_EACH_VEC_ELT (region->params, i, p)
360 if (p == name)
361 return i;
363 return -1;
366 /* Extract an affine expression from the tree E in the scop S. */
368 static isl_pw_aff *
369 extract_affine (scop_p s, tree e, __isl_take isl_space *space)
371 isl_pw_aff *lhs, *rhs, *res;
373 if (e == chrec_dont_know) {
374 isl_space_free (space);
375 return NULL;
378 switch (TREE_CODE (e))
380 case POLYNOMIAL_CHREC:
381 res = extract_affine_chrec (s, e, space);
382 break;
384 case MULT_EXPR:
385 res = extract_affine_mul (s, e, space);
386 break;
388 case PLUS_EXPR:
389 case POINTER_PLUS_EXPR:
390 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
391 rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
392 res = isl_pw_aff_add (lhs, rhs);
393 break;
395 case MINUS_EXPR:
396 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
397 rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
398 res = isl_pw_aff_sub (lhs, rhs);
399 break;
401 case NEGATE_EXPR:
402 case BIT_NOT_EXPR:
403 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
404 rhs = extract_affine (s, integer_minus_one_node, space);
405 res = isl_pw_aff_mul (lhs, rhs);
406 break;
408 case SSA_NAME:
409 gcc_assert (-1 != parameter_index_in_region_1 (e, s->scop_info)
410 || defined_in_sese_p (e, s->scop_info->region));
411 res = extract_affine_name (s, e, space);
412 break;
414 case INTEGER_CST:
415 res = extract_affine_int (e, space);
416 /* No need to wrap a single integer. */
417 return res;
419 CASE_CONVERT:
420 case NON_LVALUE_EXPR:
421 res = extract_affine (s, TREE_OPERAND (e, 0), space);
422 break;
424 default:
425 gcc_unreachable ();
426 break;
429 tree type = TREE_TYPE (e);
430 if (TYPE_UNSIGNED (type))
431 res = wrap (res, TYPE_PRECISION (type));
433 return res;
436 /* Returns a linear expression for tree T evaluated in PBB. */
438 static isl_pw_aff *
439 create_pw_aff_from_tree (poly_bb_p pbb, loop_p loop, tree t)
441 scop_p scop = PBB_SCOP (pbb);
443 t = scalar_evolution_in_region (scop->scop_info->region, loop, t);
445 gcc_assert (!chrec_contains_undetermined (t));
446 gcc_assert (!automatically_generated_chrec_p (t));
448 return extract_affine (scop, t, isl_set_get_space (pbb->domain));
451 /* Add conditional statement STMT to pbb. CODE is used as the comparison
452 operator. This allows us to invert the condition or to handle
453 inequalities. */
455 static void
456 add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code)
458 loop_p loop = gimple_bb (stmt)->loop_father;
459 isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_lhs (stmt));
460 isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_rhs (stmt));
462 isl_set *cond;
463 switch (code)
465 case LT_EXPR:
466 cond = isl_pw_aff_lt_set (lhs, rhs);
467 break;
469 case GT_EXPR:
470 cond = isl_pw_aff_gt_set (lhs, rhs);
471 break;
473 case LE_EXPR:
474 cond = isl_pw_aff_le_set (lhs, rhs);
475 break;
477 case GE_EXPR:
478 cond = isl_pw_aff_ge_set (lhs, rhs);
479 break;
481 case EQ_EXPR:
482 cond = isl_pw_aff_eq_set (lhs, rhs);
483 break;
485 case NE_EXPR:
486 cond = isl_pw_aff_ne_set (lhs, rhs);
487 break;
489 default:
490 gcc_unreachable ();
493 cond = isl_set_coalesce (cond);
494 cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain));
495 pbb->domain = isl_set_coalesce (isl_set_intersect (pbb->domain, cond));
498 /* Add conditions to the domain of PBB. */
500 static void
501 add_conditions_to_domain (poly_bb_p pbb)
503 unsigned int i;
504 gimple *stmt;
505 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
507 if (GBB_CONDITIONS (gbb).is_empty ())
508 return;
510 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
511 switch (gimple_code (stmt))
513 case GIMPLE_COND:
515 /* Don't constrain on anything else than INTEGER_TYPE. */
516 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt))) != INTEGER_TYPE)
517 break;
519 gcond *cond_stmt = as_a <gcond *> (stmt);
520 enum tree_code code = gimple_cond_code (cond_stmt);
522 /* The conditions for ELSE-branches are inverted. */
523 if (!GBB_CONDITION_CASES (gbb)[i])
524 code = invert_tree_comparison (code, false);
526 add_condition_to_pbb (pbb, cond_stmt, code);
527 break;
530 default:
531 gcc_unreachable ();
532 break;
536 /* Add constraints on the possible values of parameter P from the type
537 of P. */
539 static void
540 add_param_constraints (scop_p scop, graphite_dim_t p)
542 tree parameter = scop->scop_info->params[p];
543 tree type = TREE_TYPE (parameter);
544 tree lb = NULL_TREE;
545 tree ub = NULL_TREE;
547 if (POINTER_TYPE_P (type) || !TYPE_MIN_VALUE (type))
548 lb = lower_bound_in_type (type, type);
549 else
550 lb = TYPE_MIN_VALUE (type);
552 if (POINTER_TYPE_P (type) || !TYPE_MAX_VALUE (type))
553 ub = upper_bound_in_type (type, type);
554 else
555 ub = TYPE_MAX_VALUE (type);
557 if (lb)
559 isl_space *space = isl_set_get_space (scop->param_context);
560 isl_constraint *c;
561 mpz_t g;
562 isl_val *v;
564 c = isl_inequality_alloc (isl_local_space_from_space (space));
565 mpz_init (g);
566 tree_int_to_gmp (lb, g);
567 v = isl_val_int_from_gmp (scop->isl_context, g);
568 v = isl_val_neg (v);
569 mpz_clear (g);
570 c = isl_constraint_set_constant_val (c, v);
571 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, 1);
573 scop->param_context = isl_set_coalesce
574 (isl_set_add_constraint (scop->param_context, c));
577 if (ub)
579 isl_space *space = isl_set_get_space (scop->param_context);
580 isl_constraint *c;
581 mpz_t g;
582 isl_val *v;
584 c = isl_inequality_alloc (isl_local_space_from_space (space));
586 mpz_init (g);
587 tree_int_to_gmp (ub, g);
588 v = isl_val_int_from_gmp (scop->isl_context, g);
589 mpz_clear (g);
590 c = isl_constraint_set_constant_val (c, v);
591 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, -1);
593 scop->param_context = isl_set_coalesce
594 (isl_set_add_constraint (scop->param_context, c));
598 /* Add a constrain to the ACCESSES polyhedron for the alias set of
599 data reference DR. ACCESSP_NB_DIMS is the dimension of the
600 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
601 domain. */
603 static isl_map *
604 pdr_add_alias_set (isl_map *acc, dr_info &dri)
606 isl_constraint *c = isl_equality_alloc
607 (isl_local_space_from_space (isl_map_get_space (acc)));
608 /* Positive numbers for all alias sets. */
609 c = isl_constraint_set_constant_si (c, -dri.alias_set);
610 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
612 return isl_map_add_constraint (acc, c);
615 /* Add a constrain to the ACCESSES polyhedron for the alias set of
616 data reference DR. ACCESSP_NB_DIMS is the dimension of the
617 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
618 domain. */
620 static isl_map *
621 add_scalar_version_numbers (isl_map *acc, tree var)
623 isl_constraint *c = isl_equality_alloc
624 (isl_local_space_from_space (isl_map_get_space (acc)));
625 int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP);
626 /* Each scalar variables has a unique alias set number starting from
627 max_arrays. */
628 c = isl_constraint_set_constant_si (c, -max_arrays - SSA_NAME_VERSION (var));
629 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
631 return isl_map_add_constraint (acc, c);
634 /* Assign the affine expression INDEX to the output dimension POS of
635 MAP and return the result. */
637 static isl_map *
638 set_index (isl_map *map, int pos, isl_pw_aff *index)
640 isl_map *index_map;
641 int len = isl_map_dim (map, isl_dim_out);
642 isl_id *id;
644 index_map = isl_map_from_pw_aff (index);
645 index_map = isl_map_insert_dims (index_map, isl_dim_out, 0, pos);
646 index_map = isl_map_add_dims (index_map, isl_dim_out, len - pos - 1);
648 id = isl_map_get_tuple_id (map, isl_dim_out);
649 index_map = isl_map_set_tuple_id (index_map, isl_dim_out, id);
650 id = isl_map_get_tuple_id (map, isl_dim_in);
651 index_map = isl_map_set_tuple_id (index_map, isl_dim_in, id);
653 return isl_map_intersect (map, index_map);
656 /* Add to ACCESSES polyhedron equalities defining the access functions
657 to the memory. ACCESSP_NB_DIMS is the dimension of the ACCESSES
658 polyhedron, DOM_NB_DIMS is the dimension of the iteration domain.
659 PBB is the poly_bb_p that contains the data reference DR. */
661 static isl_map *
662 pdr_add_memory_accesses (isl_map *acc, dr_info &dri)
664 data_reference_p dr = dri.dr;
665 poly_bb_p pbb = dri.pbb;
666 int i, nb_subscripts = DR_NUM_DIMENSIONS (dr);
667 scop_p scop = PBB_SCOP (pbb);
669 for (i = 0; i < nb_subscripts; i++)
671 isl_pw_aff *aff;
672 tree afn = DR_ACCESS_FN (dr, i);
674 aff = extract_affine (scop, afn,
675 isl_space_domain (isl_map_get_space (acc)));
676 acc = set_index (acc, nb_subscripts - i , aff);
679 return isl_map_coalesce (acc);
682 /* Return true when the LOW and HIGH bounds of an array reference REF are valid
683 to extract constraints on accessed elements of the array. Returning false is
684 the conservative answer. */
686 static bool
687 bounds_are_valid (tree ref, tree low, tree high)
689 if (!high)
690 return false;
692 if (!tree_fits_shwi_p (low)
693 || !tree_fits_shwi_p (high))
694 return false;
696 /* 1-element arrays at end of structures may extend over
697 their declared size. */
698 if (array_at_struct_end_p (ref)
699 && operand_equal_p (low, high, 0))
700 return false;
702 /* Fortran has some arrays where high bound is -1 and low is 0. */
703 if (integer_onep (fold_build2 (LT_EXPR, boolean_type_node, high, low)))
704 return false;
706 return true;
709 /* Add constrains representing the size of the accessed data to the
710 ACCESSES polyhedron. ACCESSP_NB_DIMS is the dimension of the
711 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
712 domain. */
714 static isl_set *
715 pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop,
716 data_reference_p dr)
718 tree ref = DR_REF (dr);
720 int nb_subscripts = DR_NUM_DIMENSIONS (dr);
721 for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0))
723 if (TREE_CODE (ref) != ARRAY_REF)
724 return subscript_sizes;
726 tree low = array_ref_low_bound (ref);
727 tree high = array_ref_up_bound (ref);
729 if (!bounds_are_valid (ref, low, high))
730 continue;
732 isl_space *space = isl_set_get_space (subscript_sizes);
733 isl_pw_aff *lb = extract_affine_int (low, isl_space_copy (space));
734 isl_pw_aff *ub = extract_affine_int (high, isl_space_copy (space));
736 /* high >= 0 */
737 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub));
738 valid = isl_set_project_out (valid, isl_dim_set, 0,
739 isl_set_dim (valid, isl_dim_set));
740 scop->param_context = isl_set_coalesce
741 (isl_set_intersect (scop->param_context, valid));
743 isl_aff *aff
744 = isl_aff_zero_on_domain (isl_local_space_from_space (space));
745 aff = isl_aff_add_coefficient_si (aff, isl_dim_in, i + 1, 1);
746 isl_set *univ
747 = isl_set_universe (isl_space_domain (isl_aff_get_space (aff)));
748 isl_pw_aff *index = isl_pw_aff_alloc (univ, aff);
750 isl_id *id = isl_set_get_tuple_id (subscript_sizes);
751 lb = isl_pw_aff_set_tuple_id (lb, isl_dim_in, isl_id_copy (id));
752 ub = isl_pw_aff_set_tuple_id (ub, isl_dim_in, id);
754 /* low <= sub_i <= high */
755 isl_set *lbs = isl_pw_aff_ge_set (isl_pw_aff_copy (index), lb);
756 isl_set *ubs = isl_pw_aff_le_set (index, ub);
757 subscript_sizes = isl_set_intersect (subscript_sizes, lbs);
758 subscript_sizes = isl_set_intersect (subscript_sizes, ubs);
761 return isl_set_coalesce (subscript_sizes);
764 /* Build data accesses for DRI. */
766 static void
767 build_poly_dr (dr_info &dri)
769 isl_map *acc;
770 isl_set *subscript_sizes;
771 poly_bb_p pbb = dri.pbb;
772 data_reference_p dr = dri.dr;
773 scop_p scop = PBB_SCOP (pbb);
774 isl_id *id = isl_id_for_dr (scop);
777 isl_space *dc = isl_set_get_space (pbb->domain);
778 int nb_out = 1 + DR_NUM_DIMENSIONS (dr);
779 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
780 isl_dim_out, nb_out);
782 acc = isl_map_universe (space);
783 acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id));
786 acc = pdr_add_alias_set (acc, dri);
787 acc = pdr_add_memory_accesses (acc, dri);
790 int nb = 1 + DR_NUM_DIMENSIONS (dr);
791 isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb);
793 space = isl_space_set_tuple_id (space, isl_dim_set, id);
794 subscript_sizes = isl_set_nat_universe (space);
795 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
796 dri.alias_set);
797 subscript_sizes = pdr_add_data_dimensions (subscript_sizes, scop, dr);
800 new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE,
801 acc, subscript_sizes);
804 static void
805 build_poly_sr_1 (poly_bb_p pbb, gimple *stmt, tree var, enum poly_dr_type kind,
806 isl_map *acc, isl_set *subscript_sizes)
808 int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP);
809 /* Each scalar variables has a unique alias set number starting from
810 max_arrays. */
811 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
812 max_arrays + SSA_NAME_VERSION (var));
814 new_poly_dr (pbb, stmt, kind, add_scalar_version_numbers (acc, var),
815 subscript_sizes);
818 /* Record all cross basic block scalar variables in PBB. */
820 static void
821 build_poly_sr (poly_bb_p pbb)
823 scop_p scop = PBB_SCOP (pbb);
824 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
825 vec<scalar_use> &reads = gbb->read_scalar_refs;
826 vec<tree> &writes = gbb->write_scalar_refs;
828 isl_space *dc = isl_set_get_space (pbb->domain);
829 int nb_out = 1;
830 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
831 isl_dim_out, nb_out);
832 isl_id *id = isl_id_for_dr (scop);
833 space = isl_space_set_tuple_id (space, isl_dim_set, isl_id_copy (id));
834 isl_map *acc = isl_map_universe (isl_space_copy (space));
835 acc = isl_map_set_tuple_id (acc, isl_dim_out, id);
836 isl_set *subscript_sizes = isl_set_nat_universe (space);
838 int i;
839 tree var;
840 FOR_EACH_VEC_ELT (writes, i, var)
841 build_poly_sr_1 (pbb, SSA_NAME_DEF_STMT (var), var, PDR_WRITE,
842 isl_map_copy (acc), isl_set_copy (subscript_sizes));
844 scalar_use *use;
845 FOR_EACH_VEC_ELT (reads, i, use)
846 build_poly_sr_1 (pbb, use->first, use->second, PDR_READ, isl_map_copy (acc),
847 isl_set_copy (subscript_sizes));
849 isl_map_free (acc);
850 isl_set_free (subscript_sizes);
853 /* Build data references in SCOP. */
855 static void
856 build_scop_drs (scop_p scop)
858 int i;
859 dr_info *dri;
860 FOR_EACH_VEC_ELT (scop->drs, i, dri)
861 build_poly_dr (*dri);
863 poly_bb_p pbb;
864 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
865 build_poly_sr (pbb);
868 /* Add to the iteration DOMAIN one extra dimension for LOOP->num. */
870 static isl_set *
871 add_iter_domain_dimension (__isl_take isl_set *domain, loop_p loop, scop_p scop)
873 int loop_index = isl_set_dim (domain, isl_dim_set);
874 domain = isl_set_add_dims (domain, isl_dim_set, 1);
875 char name[50];
876 snprintf (name, sizeof(name), "i%d", loop->num);
877 isl_id *label = isl_id_alloc (scop->isl_context, name, NULL);
878 return isl_set_set_dim_id (domain, isl_dim_set, loop_index, label);
881 /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */
883 static isl_set *
884 add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop,
885 loop_p context)
887 if (loop == context)
888 return domain;
889 const sese_l &region = scop->scop_info->region;
890 if (!loop_in_sese_p (loop, region))
891 return domain;
893 /* Recursion all the way up to the context loop. */
894 domain = add_loop_constraints (scop, domain, loop_outer (loop), context);
896 /* Then, build constraints over the loop in post-order: outer to inner. */
898 int loop_index = isl_set_dim (domain, isl_dim_set);
899 if (dump_file)
900 fprintf (dump_file, "[sese-to-poly] adding one extra dimension to the "
901 "domain for loop_%d.\n", loop->num);
902 domain = add_iter_domain_dimension (domain, loop, scop);
903 isl_space *space = isl_set_get_space (domain);
905 /* 0 <= loop_i */
906 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
907 isl_constraint *c = isl_inequality_alloc (ls);
908 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, 1);
909 if (dump_file)
911 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
912 print_isl_constraint (dump_file, c);
914 domain = isl_set_add_constraint (domain, c);
916 tree nb_iters = number_of_latch_executions (loop);
917 if (TREE_CODE (nb_iters) == INTEGER_CST)
919 /* loop_i <= cst_nb_iters */
920 isl_local_space *ls = isl_local_space_from_space (space);
921 isl_constraint *c = isl_inequality_alloc (ls);
922 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
923 mpz_t g;
924 mpz_init (g);
925 tree_int_to_gmp (nb_iters, g);
926 isl_val *v = isl_val_int_from_gmp (scop->isl_context, g);
927 mpz_clear (g);
928 c = isl_constraint_set_constant_val (c, v);
929 return isl_set_add_constraint (domain, c);
931 /* loop_i <= expr_nb_iters */
932 gcc_assert (!chrec_contains_undetermined (nb_iters));
933 nb_iters = scalar_evolution_in_region (region, loop, nb_iters);
934 gcc_assert (!chrec_contains_undetermined (nb_iters));
936 isl_pw_aff *aff_nb_iters = extract_affine (scop, nb_iters,
937 isl_space_copy (space));
938 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters));
939 valid = isl_set_project_out (valid, isl_dim_set, 0,
940 isl_set_dim (valid, isl_dim_set));
942 if (valid)
943 scop->param_context = isl_set_intersect (scop->param_context, valid);
945 ls = isl_local_space_from_space (isl_space_copy (space));
946 isl_aff *loop_i = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls),
947 isl_dim_in, loop_index, 1);
948 isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i),
949 isl_pw_aff_copy (aff_nb_iters));
950 if (dump_file)
952 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
953 print_isl_set (dump_file, le);
955 domain = isl_set_intersect (domain, le);
957 widest_int nit;
958 if (!max_stmt_executions (loop, &nit))
960 isl_pw_aff_free (aff_nb_iters);
961 isl_space_free (space);
962 return domain;
965 /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we
966 do not know whether the loop executes at least once. */
967 mpz_t g;
968 mpz_init (g);
969 wi::to_mpz (nit, g, SIGNED);
970 mpz_sub_ui (g, g, 1);
972 isl_pw_aff *approx = extract_affine_gmp (g, isl_space_copy (space));
973 isl_set *x = isl_pw_aff_ge_set (approx, aff_nb_iters);
974 x = isl_set_project_out (x, isl_dim_set, 0,
975 isl_set_dim (x, isl_dim_set));
976 scop->param_context = isl_set_intersect (scop->param_context, x);
978 ls = isl_local_space_from_space (space);
979 c = isl_inequality_alloc (ls);
980 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
981 isl_val *v = isl_val_int_from_gmp (scop->isl_context, g);
982 mpz_clear (g);
983 c = isl_constraint_set_constant_val (c, v);
985 if (dump_file)
987 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
988 print_isl_constraint (dump_file, c);
991 return isl_set_add_constraint (domain, c);
994 /* Builds the original iteration domains for each pbb in the SCOP. */
996 static int
997 build_iteration_domains (scop_p scop, __isl_keep isl_set *context,
998 int index, loop_p context_loop)
1000 loop_p current = pbb_loop (scop->pbbs[index]);
1001 isl_set *domain = isl_set_copy (context);
1002 domain = add_loop_constraints (scop, domain, current, context_loop);
1003 const sese_l &region = scop->scop_info->region;
1005 int i;
1006 poly_bb_p pbb;
1007 FOR_EACH_VEC_ELT_FROM (scop->pbbs, i, pbb, index)
1009 loop_p loop = pbb_loop (pbb);
1010 if (current == loop)
1012 #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
1013 pbb->iterators = isl_set_copy (domain);
1014 #endif
1015 pbb->domain = isl_set_copy (domain);
1016 pbb->domain = isl_set_set_tuple_id (pbb->domain,
1017 isl_id_for_pbb (scop, pbb));
1018 add_conditions_to_domain (pbb);
1020 if (dump_file)
1022 fprintf (dump_file, "[sese-to-poly] set pbb_%d->domain: ",
1023 pbb_index (pbb));
1024 print_isl_set (dump_file, domain);
1026 continue;
1029 while (loop_in_sese_p (loop, region)
1030 && current != loop)
1031 loop = loop_outer (loop);
1033 if (current != loop)
1035 /* A statement in a different loop nest than CURRENT loop. */
1036 isl_set_free (domain);
1037 return i;
1040 /* A statement nested in the CURRENT loop. */
1041 i = build_iteration_domains (scop, domain, i, current);
1042 i--;
1045 isl_set_free (domain);
1046 return i;
1049 /* Assign dimension for each parameter in SCOP and add constraints for the
1050 parameters. */
1052 static void
1053 build_scop_context (scop_p scop)
1055 sese_info_p region = scop->scop_info;
1056 unsigned nbp = sese_nb_params (region);
1057 isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0);
1059 unsigned i;
1060 tree e;
1061 FOR_EACH_VEC_ELT (region->params, i, e)
1062 space = isl_space_set_dim_id (space, isl_dim_param, i,
1063 isl_id_for_ssa_name (scop, e));
1065 scop->param_context = isl_set_universe (space);
1067 graphite_dim_t p;
1068 for (p = 0; p < nbp; p++)
1069 add_param_constraints (scop, p);
1072 #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
1074 /* Return true when loop A is nested in loop B. */
1076 static bool
1077 nested_in (loop_p a, loop_p b)
1079 return b == find_common_loop (a, b);
1082 /* Return the loop at a specific SCOP->pbbs[*INDEX]. */
1083 static loop_p
1084 loop_at (scop_p scop, int *index)
1086 return pbb_loop (scop->pbbs[*index]);
1089 /* Return the index of any pbb belonging to loop or a subloop of A. */
1091 static int
1092 index_outermost_in_loop (loop_p a, scop_p scop)
1094 int i, outermost = -1;
1095 int last_depth = -1;
1096 poly_bb_p pbb;
1097 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
1098 if (nested_in (pbb_loop (pbb), a)
1099 && (last_depth == -1
1100 || last_depth > (int) loop_depth (pbb_loop (pbb))))
1102 outermost = i;
1103 last_depth = loop_depth (pbb_loop (pbb));
1105 return outermost;
1108 /* Return the index of any pbb belonging to loop or a subloop of A. */
1110 static int
1111 index_pbb_in_loop (loop_p a, scop_p scop)
1113 int i;
1114 poly_bb_p pbb;
1115 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
1116 if (pbb_loop (pbb) == a)
1117 return i;
1118 return -1;
1121 static poly_bb_p
1122 outermost_pbb_in (loop_p loop, scop_p scop)
1124 int x = index_pbb_in_loop (loop, scop);
1125 if (x == -1)
1126 x = index_outermost_in_loop (loop, scop);
1127 return scop->pbbs[x];
1130 static isl_schedule *
1131 add_in_sequence (__isl_take isl_schedule *a, __isl_take isl_schedule *b)
1133 gcc_assert (a || b);
1135 if (!a)
1136 return b;
1138 if (!b)
1139 return a;
1141 return isl_schedule_sequence (a, b);
1144 struct map_to_dimension_data {
1145 int n;
1146 isl_union_pw_multi_aff *res;
1149 /* Create a function that maps the elements of SET to its N-th dimension and add
1150 it to USER->res. */
1152 static isl_stat
1153 add_outer_projection (__isl_take isl_set *set, void *user)
1155 struct map_to_dimension_data *data = (struct map_to_dimension_data *) user;
1156 int dim = isl_set_dim (set, isl_dim_set);
1157 isl_space *space = isl_set_get_space (set);
1159 gcc_assert (dim >= data->n);
1160 isl_pw_multi_aff *pma
1161 = isl_pw_multi_aff_project_out_map (space, isl_dim_set, data->n,
1162 dim - data->n);
1163 data->res = isl_union_pw_multi_aff_add_pw_multi_aff (data->res, pma);
1165 isl_set_free (set);
1166 return isl_stat_ok;
1169 /* Return SET in which all inner dimensions above N are removed. */
1171 static isl_multi_union_pw_aff *
1172 outer_projection_mupa (__isl_take isl_union_set *set, int n)
1174 gcc_assert (n >= 0);
1175 gcc_assert (set);
1176 gcc_assert (!isl_union_set_is_empty (set));
1178 isl_space *space = isl_union_set_get_space (set);
1179 isl_union_pw_multi_aff *pwaff = isl_union_pw_multi_aff_empty (space);
1181 struct map_to_dimension_data data = {n, pwaff};
1183 if (isl_union_set_foreach_set (set, &add_outer_projection, &data) < 0)
1184 data.res = isl_union_pw_multi_aff_free (data.res);
1186 isl_union_set_free (set);
1187 return isl_multi_union_pw_aff_from_union_pw_multi_aff (data.res);
1190 /* Embed SCHEDULE in the constraints of the LOOP domain. */
1192 static isl_schedule *
1193 add_loop_schedule (__isl_take isl_schedule *schedule, loop_p loop,
1194 scop_p scop)
1196 poly_bb_p pbb = outermost_pbb_in (loop, scop);
1197 isl_set *iterators = pbb->iterators;
1199 int empty = isl_set_is_empty (iterators);
1200 if (empty < 0 || empty)
1201 return empty < 0 ? isl_schedule_free (schedule) : schedule;
1203 isl_space *space = isl_set_get_space (iterators);
1204 int loop_index = isl_space_dim (space, isl_dim_set) - 1;
1206 loop_p ploop = pbb_loop (pbb);
1207 while (loop != ploop)
1209 --loop_index;
1210 ploop = loop_outer (ploop);
1213 isl_local_space *ls = isl_local_space_from_space (space);
1214 isl_aff *aff = isl_aff_var_on_domain (ls, isl_dim_set, loop_index);
1215 isl_multi_aff *prefix = isl_multi_aff_from_aff (aff);
1216 char name[50];
1217 snprintf (name, sizeof(name), "L_%d", loop->num);
1218 isl_id *label = isl_id_alloc (isl_schedule_get_ctx (schedule),
1219 name, NULL);
1220 prefix = isl_multi_aff_set_tuple_id (prefix, isl_dim_out, label);
1222 int n = isl_multi_aff_dim (prefix, isl_dim_in);
1223 isl_union_set *domain = isl_schedule_get_domain (schedule);
1224 isl_multi_union_pw_aff *mupa = outer_projection_mupa (domain, n);
1225 mupa = isl_multi_union_pw_aff_apply_multi_aff (mupa, prefix);
1226 return isl_schedule_insert_partial_schedule (schedule, mupa);
1229 /* Build schedule for the pbb at INDEX. */
1231 static isl_schedule *
1232 build_schedule_pbb (scop_p scop, int *index)
1234 poly_bb_p pbb = scop->pbbs[*index];
1235 ++*index;
1236 isl_set *domain = isl_set_copy (pbb->domain);
1237 isl_union_set *ud = isl_union_set_from_set (domain);
1238 return isl_schedule_from_domain (ud);
1241 static isl_schedule *build_schedule_loop_nest (scop_p, int *, loop_p);
1243 /* Build the schedule of the loop containing the SCOP pbb at INDEX. */
1245 static isl_schedule *
1246 build_schedule_loop (scop_p scop, int *index)
1248 int max = scop->pbbs.length ();
1249 gcc_assert (*index < max);
1250 loop_p loop = loop_at (scop, index);
1252 isl_schedule *s = NULL;
1253 while (nested_in (loop_at (scop, index), loop))
1255 if (loop == loop_at (scop, index))
1256 s = add_in_sequence (s, build_schedule_pbb (scop, index));
1257 else
1258 s = add_in_sequence (s, build_schedule_loop_nest (scop, index, loop));
1260 if (*index == max)
1261 break;
1264 return add_loop_schedule (s, loop, scop);
1267 /* S is the schedule of the loop LOOP. Embed the schedule S in all outer loops.
1268 When CONTEXT_LOOP is null, embed the schedule in all loops contained in the
1269 SCOP surrounding LOOP. When CONTEXT_LOOP is non null, only embed S in the
1270 maximal loop nest contained within CONTEXT_LOOP. */
1272 static isl_schedule *
1273 embed_in_surrounding_loops (__isl_take isl_schedule *s, scop_p scop,
1274 loop_p loop, int *index, loop_p context_loop)
1276 loop_p outer = loop_outer (loop);
1277 sese_l region = scop->scop_info->region;
1278 if (context_loop == outer
1279 || !loop_in_sese_p (outer, region))
1280 return s;
1282 int max = scop->pbbs.length ();
1283 if (*index == max
1284 || (context_loop && !nested_in (loop_at (scop, index), context_loop))
1285 || (!context_loop
1286 && !loop_in_sese_p (find_common_loop (outer, loop_at (scop, index)),
1287 region)))
1288 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop),
1289 scop, outer, index, context_loop);
1291 bool a_pbb;
1292 while ((a_pbb = (outer == loop_at (scop, index)))
1293 || nested_in (loop_at (scop, index), outer))
1295 if (a_pbb)
1296 s = add_in_sequence (s, build_schedule_pbb (scop, index));
1297 else
1298 s = add_in_sequence (s, build_schedule_loop (scop, index));
1300 if (*index == max)
1301 break;
1304 /* We reached the end of the OUTER loop: embed S in OUTER. */
1305 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), scop,
1306 outer, index, context_loop);
1309 /* Build schedule for the full loop nest containing the pbb at INDEX. When
1310 CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP
1311 surrounding the pbb. When CONTEXT_LOOP is non null, only build the maximal loop
1312 nest contained within CONTEXT_LOOP. */
1314 static isl_schedule *
1315 build_schedule_loop_nest (scop_p scop, int *index, loop_p context_loop)
1317 gcc_assert (*index != (int) scop->pbbs.length ());
1319 loop_p loop = loop_at (scop, index);
1320 isl_schedule *s = build_schedule_loop (scop, index);
1321 return embed_in_surrounding_loops (s, scop, loop, index, context_loop);
1324 /* Build the schedule of the SCOP. */
1326 static bool
1327 build_original_schedule (scop_p scop)
1329 int i = 0;
1330 int n = scop->pbbs.length ();
1331 while (i < n)
1333 poly_bb_p pbb = scop->pbbs[i];
1334 isl_schedule *s = NULL;
1335 if (!loop_in_sese_p (pbb_loop (pbb), scop->scop_info->region))
1336 s = build_schedule_pbb (scop, &i);
1337 else
1338 s = build_schedule_loop_nest (scop, &i, NULL);
1340 scop->original_schedule = add_in_sequence (scop->original_schedule, s);
1343 if (dump_file)
1345 fprintf (dump_file, "[sese-to-poly] original schedule:\n");
1346 print_isl_schedule (dump_file, scop->original_schedule);
1348 if (!scop->original_schedule)
1349 return false;
1350 return true;
1353 #endif
1355 /* Builds the polyhedral representation for a SESE region. */
1357 bool
1358 build_poly_scop (scop_p scop)
1360 build_scop_context (scop);
1362 unsigned i = 0;
1363 unsigned n = scop->pbbs.length ();
1364 while (i < n)
1365 i = build_iteration_domains (scop, scop->param_context, i, NULL);
1367 build_scop_drs (scop);
1368 #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
1369 build_original_schedule (scop);
1370 #else
1371 build_scop_scattering (scop);
1372 #endif
1373 return true;
1375 #endif /* HAVE_isl */