Use gfc_add_*_component defines where appropriate
[official-gcc.git] / gcc / graphite-sese-to-poly.c
blob22a09a1782ff71871d8b408841c1c291982f95c3
1 /* Conversion of SESE regions to Polyhedra.
2 Copyright (C) 2009-2016 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[10];
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[10];
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 || !invariant_in_sese_p_rec (e, s->scop_info->region, NULL));
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, tree t)
441 scop_p scop = PBB_SCOP (pbb);
443 t = scalar_evolution_in_region (scop->scop_info->region, pbb_loop (pbb), 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 isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, gimple_cond_lhs (stmt));
459 isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, gimple_cond_rhs (stmt));
461 isl_set *cond;
462 switch (code)
464 case LT_EXPR:
465 cond = isl_pw_aff_lt_set (lhs, rhs);
466 break;
468 case GT_EXPR:
469 cond = isl_pw_aff_gt_set (lhs, rhs);
470 break;
472 case LE_EXPR:
473 cond = isl_pw_aff_le_set (lhs, rhs);
474 break;
476 case GE_EXPR:
477 cond = isl_pw_aff_ge_set (lhs, rhs);
478 break;
480 case EQ_EXPR:
481 cond = isl_pw_aff_eq_set (lhs, rhs);
482 break;
484 case NE_EXPR:
485 cond = isl_pw_aff_ne_set (lhs, rhs);
486 break;
488 default:
489 gcc_unreachable ();
492 cond = isl_set_coalesce (cond);
493 cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain));
494 pbb->domain = isl_set_coalesce (isl_set_intersect (pbb->domain, cond));
497 /* Add conditions to the domain of PBB. */
499 static void
500 add_conditions_to_domain (poly_bb_p pbb)
502 unsigned int i;
503 gimple *stmt;
504 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
506 if (GBB_CONDITIONS (gbb).is_empty ())
507 return;
509 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
510 switch (gimple_code (stmt))
512 case GIMPLE_COND:
514 /* Don't constrain on anything else than INTEGER_TYPE. */
515 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt))) != INTEGER_TYPE)
516 break;
518 gcond *cond_stmt = as_a <gcond *> (stmt);
519 enum tree_code code = gimple_cond_code (cond_stmt);
521 /* The conditions for ELSE-branches are inverted. */
522 if (!GBB_CONDITION_CASES (gbb)[i])
523 code = invert_tree_comparison (code, false);
525 add_condition_to_pbb (pbb, cond_stmt, code);
526 break;
529 default:
530 gcc_unreachable ();
531 break;
535 /* Add constraints on the possible values of parameter P from the type
536 of P. */
538 static void
539 add_param_constraints (scop_p scop, graphite_dim_t p)
541 tree parameter = scop->scop_info->params[p];
542 tree type = TREE_TYPE (parameter);
543 tree lb = NULL_TREE;
544 tree ub = NULL_TREE;
546 if (POINTER_TYPE_P (type) || !TYPE_MIN_VALUE (type))
547 lb = lower_bound_in_type (type, type);
548 else
549 lb = TYPE_MIN_VALUE (type);
551 if (POINTER_TYPE_P (type) || !TYPE_MAX_VALUE (type))
552 ub = upper_bound_in_type (type, type);
553 else
554 ub = TYPE_MAX_VALUE (type);
556 if (lb)
558 isl_space *space = isl_set_get_space (scop->param_context);
559 isl_constraint *c;
560 mpz_t g;
561 isl_val *v;
563 c = isl_inequality_alloc (isl_local_space_from_space (space));
564 mpz_init (g);
565 tree_int_to_gmp (lb, g);
566 v = isl_val_int_from_gmp (scop->isl_context, g);
567 v = isl_val_neg (v);
568 mpz_clear (g);
569 c = isl_constraint_set_constant_val (c, v);
570 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, 1);
572 scop->param_context = isl_set_coalesce
573 (isl_set_add_constraint (scop->param_context, c));
576 if (ub)
578 isl_space *space = isl_set_get_space (scop->param_context);
579 isl_constraint *c;
580 mpz_t g;
581 isl_val *v;
583 c = isl_inequality_alloc (isl_local_space_from_space (space));
585 mpz_init (g);
586 tree_int_to_gmp (ub, g);
587 v = isl_val_int_from_gmp (scop->isl_context, g);
588 mpz_clear (g);
589 c = isl_constraint_set_constant_val (c, v);
590 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, -1);
592 scop->param_context = isl_set_coalesce
593 (isl_set_add_constraint (scop->param_context, c));
597 /* Add a constrain to the ACCESSES polyhedron for the alias set of
598 data reference DR. ACCESSP_NB_DIMS is the dimension of the
599 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
600 domain. */
602 static isl_map *
603 pdr_add_alias_set (isl_map *acc, dr_info &dri)
605 isl_constraint *c = isl_equality_alloc
606 (isl_local_space_from_space (isl_map_get_space (acc)));
607 /* Positive numbers for all alias sets. */
608 c = isl_constraint_set_constant_si (c, -dri.alias_set);
609 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
611 return isl_map_add_constraint (acc, c);
614 /* Add a constrain to the ACCESSES polyhedron for the alias set of
615 data reference DR. ACCESSP_NB_DIMS is the dimension of the
616 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
617 domain. */
619 static isl_map *
620 add_scalar_version_numbers (isl_map *acc, tree var)
622 isl_constraint *c = isl_equality_alloc
623 (isl_local_space_from_space (isl_map_get_space (acc)));
624 int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP);
625 /* Each scalar variables has a unique alias set number starting from
626 max_arrays. */
627 c = isl_constraint_set_constant_si (c, -max_arrays - SSA_NAME_VERSION (var));
628 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
630 return isl_map_add_constraint (acc, c);
633 /* Assign the affine expression INDEX to the output dimension POS of
634 MAP and return the result. */
636 static isl_map *
637 set_index (isl_map *map, int pos, isl_pw_aff *index)
639 isl_map *index_map;
640 int len = isl_map_dim (map, isl_dim_out);
641 isl_id *id;
643 index_map = isl_map_from_pw_aff (index);
644 index_map = isl_map_insert_dims (index_map, isl_dim_out, 0, pos);
645 index_map = isl_map_add_dims (index_map, isl_dim_out, len - pos - 1);
647 id = isl_map_get_tuple_id (map, isl_dim_out);
648 index_map = isl_map_set_tuple_id (index_map, isl_dim_out, id);
649 id = isl_map_get_tuple_id (map, isl_dim_in);
650 index_map = isl_map_set_tuple_id (index_map, isl_dim_in, id);
652 return isl_map_intersect (map, index_map);
655 /* Add to ACCESSES polyhedron equalities defining the access functions
656 to the memory. ACCESSP_NB_DIMS is the dimension of the ACCESSES
657 polyhedron, DOM_NB_DIMS is the dimension of the iteration domain.
658 PBB is the poly_bb_p that contains the data reference DR. */
660 static isl_map *
661 pdr_add_memory_accesses (isl_map *acc, dr_info &dri)
663 data_reference_p dr = dri.dr;
664 poly_bb_p pbb = dri.pbb;
665 int i, nb_subscripts = DR_NUM_DIMENSIONS (dr);
666 scop_p scop = PBB_SCOP (pbb);
668 for (i = 0; i < nb_subscripts; i++)
670 isl_pw_aff *aff;
671 tree afn = DR_ACCESS_FN (dr, i);
673 aff = extract_affine (scop, afn,
674 isl_space_domain (isl_map_get_space (acc)));
675 acc = set_index (acc, nb_subscripts - i , aff);
678 return isl_map_coalesce (acc);
681 /* Return true when the LOW and HIGH bounds of an array reference REF are valid
682 to extract constraints on accessed elements of the array. Returning false is
683 the conservative answer. */
685 static bool
686 bounds_are_valid (tree ref, tree low, tree high)
688 if (!high)
689 return false;
691 if (!tree_fits_shwi_p (low)
692 || !tree_fits_shwi_p (high))
693 return false;
695 /* 1-element arrays at end of structures may extend over
696 their declared size. */
697 if (array_at_struct_end_p (ref)
698 && operand_equal_p (low, high, 0))
699 return false;
701 /* Fortran has some arrays where high bound is -1 and low is 0. */
702 if (integer_onep (fold_build2 (LT_EXPR, boolean_type_node, high, low)))
703 return false;
705 return true;
708 /* Add constrains representing the size of the accessed data to the
709 ACCESSES polyhedron. ACCESSP_NB_DIMS is the dimension of the
710 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
711 domain. */
713 static isl_set *
714 pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop,
715 data_reference_p dr)
717 tree ref = DR_REF (dr);
719 int nb_subscripts = DR_NUM_DIMENSIONS (dr);
720 for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0))
722 if (TREE_CODE (ref) != ARRAY_REF)
723 return subscript_sizes;
725 tree low = array_ref_low_bound (ref);
726 tree high = array_ref_up_bound (ref);
728 if (!bounds_are_valid (ref, low, high))
729 continue;
731 isl_space *space = isl_set_get_space (subscript_sizes);
732 isl_pw_aff *lb = extract_affine_int (low, isl_space_copy (space));
733 isl_pw_aff *ub = extract_affine_int (high, isl_space_copy (space));
735 /* high >= 0 */
736 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub));
737 valid = isl_set_project_out (valid, isl_dim_set, 0,
738 isl_set_dim (valid, isl_dim_set));
739 scop->param_context = isl_set_coalesce
740 (isl_set_intersect (scop->param_context, valid));
742 isl_aff *aff
743 = isl_aff_zero_on_domain (isl_local_space_from_space (space));
744 aff = isl_aff_add_coefficient_si (aff, isl_dim_in, i + 1, 1);
745 isl_set *univ
746 = isl_set_universe (isl_space_domain (isl_aff_get_space (aff)));
747 isl_pw_aff *index = isl_pw_aff_alloc (univ, aff);
749 isl_id *id = isl_set_get_tuple_id (subscript_sizes);
750 lb = isl_pw_aff_set_tuple_id (lb, isl_dim_in, isl_id_copy (id));
751 ub = isl_pw_aff_set_tuple_id (ub, isl_dim_in, id);
753 /* low <= sub_i <= high */
754 isl_set *lbs = isl_pw_aff_ge_set (isl_pw_aff_copy (index), lb);
755 isl_set *ubs = isl_pw_aff_le_set (index, ub);
756 subscript_sizes = isl_set_intersect (subscript_sizes, lbs);
757 subscript_sizes = isl_set_intersect (subscript_sizes, ubs);
760 return isl_set_coalesce (subscript_sizes);
763 /* Build data accesses for DRI. */
765 static void
766 build_poly_dr (dr_info &dri)
768 isl_map *acc;
769 isl_set *subscript_sizes;
770 poly_bb_p pbb = dri.pbb;
771 data_reference_p dr = dri.dr;
772 scop_p scop = PBB_SCOP (pbb);
773 isl_id *id = isl_id_for_dr (scop);
776 isl_space *dc = isl_set_get_space (pbb->domain);
777 int nb_out = 1 + DR_NUM_DIMENSIONS (dr);
778 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
779 isl_dim_out, nb_out);
781 acc = isl_map_universe (space);
782 acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id));
785 acc = pdr_add_alias_set (acc, dri);
786 acc = pdr_add_memory_accesses (acc, dri);
789 int nb = 1 + DR_NUM_DIMENSIONS (dr);
790 isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb);
792 space = isl_space_set_tuple_id (space, isl_dim_set, id);
793 subscript_sizes = isl_set_nat_universe (space);
794 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
795 dri.alias_set);
796 subscript_sizes = pdr_add_data_dimensions (subscript_sizes, scop, dr);
799 new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE,
800 acc, subscript_sizes);
803 static void
804 build_poly_sr_1 (poly_bb_p pbb, gimple *stmt, tree var, enum poly_dr_type kind,
805 isl_map *acc, isl_set *subscript_sizes)
807 int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP);
808 /* Each scalar variables has a unique alias set number starting from
809 max_arrays. */
810 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
811 max_arrays + SSA_NAME_VERSION (var));
813 new_poly_dr (pbb, stmt, kind, add_scalar_version_numbers (acc, var),
814 subscript_sizes);
817 /* Record all cross basic block scalar variables in PBB. */
819 static void
820 build_poly_sr (poly_bb_p pbb)
822 scop_p scop = PBB_SCOP (pbb);
823 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
824 vec<scalar_use> &reads = gbb->read_scalar_refs;
825 vec<tree> &writes = gbb->write_scalar_refs;
827 isl_space *dc = isl_set_get_space (pbb->domain);
828 int nb_out = 1;
829 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
830 isl_dim_out, nb_out);
831 isl_id *id = isl_id_for_dr (scop);
832 space = isl_space_set_tuple_id (space, isl_dim_set, isl_id_copy (id));
833 isl_map *acc = isl_map_universe (isl_space_copy (space));
834 acc = isl_map_set_tuple_id (acc, isl_dim_out, id);
835 isl_set *subscript_sizes = isl_set_nat_universe (space);
837 int i;
838 tree var;
839 FOR_EACH_VEC_ELT (writes, i, var)
840 build_poly_sr_1 (pbb, SSA_NAME_DEF_STMT (var), var, PDR_WRITE,
841 isl_map_copy (acc), isl_set_copy (subscript_sizes));
843 scalar_use *use;
844 FOR_EACH_VEC_ELT (reads, i, use)
845 build_poly_sr_1 (pbb, use->first, use->second, PDR_READ, isl_map_copy (acc),
846 isl_set_copy (subscript_sizes));
848 isl_map_free (acc);
849 isl_set_free (subscript_sizes);
852 /* Build data references in SCOP. */
854 static void
855 build_scop_drs (scop_p scop)
857 int i;
858 dr_info *dri;
859 FOR_EACH_VEC_ELT (scop->drs, i, dri)
860 build_poly_dr (*dri);
862 poly_bb_p pbb;
863 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
864 build_poly_sr (pbb);
867 /* Add to the iteration DOMAIN one extra dimension for LOOP->num. */
869 static isl_set *
870 add_iter_domain_dimension (__isl_take isl_set *domain, loop_p loop, scop_p scop)
872 int loop_index = isl_set_dim (domain, isl_dim_set);
873 domain = isl_set_add_dims (domain, isl_dim_set, 1);
874 char name[50];
875 snprintf (name, sizeof(name), "i%d", loop->num);
876 isl_id *label = isl_id_alloc (scop->isl_context, name, NULL);
877 return isl_set_set_dim_id (domain, isl_dim_set, loop_index, label);
880 /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */
882 static isl_set *
883 add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop,
884 loop_p context)
886 if (loop == context)
887 return domain;
888 const sese_l &region = scop->scop_info->region;
889 if (!loop_in_sese_p (loop, region))
890 return domain;
892 /* Recursion all the way up to the context loop. */
893 domain = add_loop_constraints (scop, domain, loop_outer (loop), context);
895 /* Then, build constraints over the loop in post-order: outer to inner. */
897 int loop_index = isl_set_dim (domain, isl_dim_set);
898 if (dump_file)
899 fprintf (dump_file, "[sese-to-poly] adding one extra dimension to the "
900 "domain for loop_%d.\n", loop->num);
901 domain = add_iter_domain_dimension (domain, loop, scop);
902 isl_space *space = isl_set_get_space (domain);
904 /* 0 <= loop_i */
905 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
906 isl_constraint *c = isl_inequality_alloc (ls);
907 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, 1);
908 if (dump_file)
910 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
911 print_isl_constraint (dump_file, c);
913 domain = isl_set_add_constraint (domain, c);
915 tree nb_iters = number_of_latch_executions (loop);
916 if (TREE_CODE (nb_iters) == INTEGER_CST)
918 /* loop_i <= cst_nb_iters */
919 isl_local_space *ls = isl_local_space_from_space (space);
920 isl_constraint *c = isl_inequality_alloc (ls);
921 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
922 mpz_t g;
923 mpz_init (g);
924 tree_int_to_gmp (nb_iters, g);
925 isl_val *v = isl_val_int_from_gmp (scop->isl_context, g);
926 mpz_clear (g);
927 c = isl_constraint_set_constant_val (c, v);
928 return isl_set_add_constraint (domain, c);
930 /* loop_i <= expr_nb_iters */
931 gcc_assert (!chrec_contains_undetermined (nb_iters));
932 nb_iters = scalar_evolution_in_region (region, loop, nb_iters);
933 gcc_assert (!chrec_contains_undetermined (nb_iters));
935 isl_pw_aff *aff_nb_iters = extract_affine (scop, nb_iters,
936 isl_space_copy (space));
937 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters));
938 valid = isl_set_project_out (valid, isl_dim_set, 0,
939 isl_set_dim (valid, isl_dim_set));
941 if (valid)
942 scop->param_context = isl_set_intersect (scop->param_context, valid);
944 ls = isl_local_space_from_space (isl_space_copy (space));
945 isl_aff *loop_i = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls),
946 isl_dim_in, loop_index, 1);
947 isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i),
948 isl_pw_aff_copy (aff_nb_iters));
949 if (dump_file)
951 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
952 print_isl_set (dump_file, le);
954 domain = isl_set_intersect (domain, le);
956 widest_int nit;
957 if (!max_stmt_executions (loop, &nit))
959 isl_pw_aff_free (aff_nb_iters);
960 isl_space_free (space);
961 return domain;
964 /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we
965 do not know whether the loop executes at least once. */
966 mpz_t g;
967 mpz_init (g);
968 wi::to_mpz (nit, g, SIGNED);
969 mpz_sub_ui (g, g, 1);
971 isl_pw_aff *approx = extract_affine_gmp (g, isl_space_copy (space));
972 isl_set *x = isl_pw_aff_ge_set (approx, aff_nb_iters);
973 x = isl_set_project_out (x, isl_dim_set, 0,
974 isl_set_dim (x, isl_dim_set));
975 scop->param_context = isl_set_intersect (scop->param_context, x);
977 ls = isl_local_space_from_space (space);
978 c = isl_inequality_alloc (ls);
979 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
980 isl_val *v = isl_val_int_from_gmp (scop->isl_context, g);
981 mpz_clear (g);
982 c = isl_constraint_set_constant_val (c, v);
984 if (dump_file)
986 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
987 print_isl_constraint (dump_file, c);
990 return isl_set_add_constraint (domain, c);
993 /* Builds the original iteration domains for each pbb in the SCOP. */
995 static int
996 build_iteration_domains (scop_p scop, __isl_keep isl_set *context,
997 int index, loop_p context_loop)
999 loop_p current = pbb_loop (scop->pbbs[index]);
1000 isl_set *domain = isl_set_copy (context);
1001 domain = add_loop_constraints (scop, domain, current, context_loop);
1002 const sese_l &region = scop->scop_info->region;
1004 int i;
1005 poly_bb_p pbb;
1006 FOR_EACH_VEC_ELT_FROM (scop->pbbs, i, pbb, index)
1008 loop_p loop = pbb_loop (pbb);
1009 if (current == loop)
1011 #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
1012 pbb->iterators = isl_set_copy (domain);
1013 #endif
1014 pbb->domain = isl_set_copy (domain);
1015 pbb->domain = isl_set_set_tuple_id (pbb->domain,
1016 isl_id_for_pbb (scop, pbb));
1017 add_conditions_to_domain (pbb);
1019 if (dump_file)
1021 fprintf (dump_file, "[sese-to-poly] set pbb_%d->domain: ",
1022 pbb_index (pbb));
1023 print_isl_set (dump_file, domain);
1025 continue;
1028 while (loop_in_sese_p (loop, region)
1029 && current != loop)
1030 loop = loop_outer (loop);
1032 if (current != loop)
1034 /* A statement in a different loop nest than CURRENT loop. */
1035 isl_set_free (domain);
1036 return i;
1039 /* A statement nested in the CURRENT loop. */
1040 i = build_iteration_domains (scop, domain, i, current);
1041 i--;
1044 isl_set_free (domain);
1045 return i;
1048 /* Assign dimension for each parameter in SCOP and add constraints for the
1049 parameters. */
1051 static void
1052 build_scop_context (scop_p scop)
1054 sese_info_p region = scop->scop_info;
1055 unsigned nbp = sese_nb_params (region);
1056 isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0);
1058 unsigned i;
1059 tree e;
1060 FOR_EACH_VEC_ELT (region->params, i, e)
1061 space = isl_space_set_dim_id (space, isl_dim_param, i,
1062 isl_id_for_ssa_name (scop, e));
1064 scop->param_context = isl_set_universe (space);
1066 graphite_dim_t p;
1067 for (p = 0; p < nbp; p++)
1068 add_param_constraints (scop, p);
1071 #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
1073 /* Return true when loop A is nested in loop B. */
1075 static bool
1076 nested_in (loop_p a, loop_p b)
1078 return b == find_common_loop (a, b);
1081 /* Return the loop at a specific SCOP->pbbs[*INDEX]. */
1082 static loop_p
1083 loop_at (scop_p scop, int *index)
1085 return pbb_loop (scop->pbbs[*index]);
1088 /* Return the index of any pbb belonging to loop or a subloop of A. */
1090 static int
1091 index_outermost_in_loop (loop_p a, scop_p scop)
1093 int i, outermost = -1;
1094 int last_depth = -1;
1095 poly_bb_p pbb;
1096 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
1097 if (nested_in (pbb_loop (pbb), a)
1098 && (last_depth == -1
1099 || last_depth > (int) loop_depth (pbb_loop (pbb))))
1101 outermost = i;
1102 last_depth = loop_depth (pbb_loop (pbb));
1104 return outermost;
1107 /* Return the index of any pbb belonging to loop or a subloop of A. */
1109 static int
1110 index_pbb_in_loop (loop_p a, scop_p scop)
1112 int i;
1113 poly_bb_p pbb;
1114 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
1115 if (pbb_loop (pbb) == a)
1116 return i;
1117 return -1;
1120 static poly_bb_p
1121 outermost_pbb_in (loop_p loop, scop_p scop)
1123 int x = index_pbb_in_loop (loop, scop);
1124 if (x == -1)
1125 x = index_outermost_in_loop (loop, scop);
1126 return scop->pbbs[x];
1129 static isl_schedule *
1130 add_in_sequence (__isl_take isl_schedule *a, __isl_take isl_schedule *b)
1132 gcc_assert (a || b);
1134 if (!a)
1135 return b;
1137 if (!b)
1138 return a;
1140 return isl_schedule_sequence (a, b);
1143 struct map_to_dimension_data {
1144 int n;
1145 isl_union_pw_multi_aff *res;
1148 /* Create a function that maps the elements of SET to its N-th dimension and add
1149 it to USER->res. */
1151 static isl_stat
1152 add_outer_projection (__isl_take isl_set *set, void *user)
1154 struct map_to_dimension_data *data = (struct map_to_dimension_data *) user;
1155 int dim = isl_set_dim (set, isl_dim_set);
1156 isl_space *space = isl_set_get_space (set);
1158 gcc_assert (dim >= data->n);
1159 isl_pw_multi_aff *pma
1160 = isl_pw_multi_aff_project_out_map (space, isl_dim_set, data->n,
1161 dim - data->n);
1162 data->res = isl_union_pw_multi_aff_add_pw_multi_aff (data->res, pma);
1164 isl_set_free (set);
1165 return isl_stat_ok;
1168 /* Return SET in which all inner dimensions above N are removed. */
1170 static isl_multi_union_pw_aff *
1171 outer_projection_mupa (__isl_take isl_union_set *set, int n)
1173 gcc_assert (n >= 0);
1174 gcc_assert (set);
1175 gcc_assert (!isl_union_set_is_empty (set));
1177 isl_space *space = isl_union_set_get_space (set);
1178 isl_union_pw_multi_aff *pwaff = isl_union_pw_multi_aff_empty (space);
1180 struct map_to_dimension_data data = {n, pwaff};
1182 if (isl_union_set_foreach_set (set, &add_outer_projection, &data) < 0)
1183 data.res = isl_union_pw_multi_aff_free (data.res);
1185 isl_union_set_free (set);
1186 return isl_multi_union_pw_aff_from_union_pw_multi_aff (data.res);
1189 /* Embed SCHEDULE in the constraints of the LOOP domain. */
1191 static isl_schedule *
1192 add_loop_schedule (__isl_take isl_schedule *schedule, loop_p loop,
1193 scop_p scop)
1195 poly_bb_p pbb = outermost_pbb_in (loop, scop);
1196 isl_set *iterators = pbb->iterators;
1198 int empty = isl_set_is_empty (iterators);
1199 if (empty < 0 || empty)
1200 return empty < 0 ? isl_schedule_free (schedule) : schedule;
1202 isl_space *space = isl_set_get_space (iterators);
1203 int loop_index = isl_space_dim (space, isl_dim_set) - 1;
1205 loop_p ploop = pbb_loop (pbb);
1206 while (loop != ploop)
1208 --loop_index;
1209 ploop = loop_outer (ploop);
1212 isl_local_space *ls = isl_local_space_from_space (space);
1213 isl_aff *aff = isl_aff_var_on_domain (ls, isl_dim_set, loop_index);
1214 isl_multi_aff *prefix = isl_multi_aff_from_aff (aff);
1215 char name[50];
1216 snprintf (name, sizeof(name), "L_%d", loop->num);
1217 isl_id *label = isl_id_alloc (isl_schedule_get_ctx (schedule),
1218 name, NULL);
1219 prefix = isl_multi_aff_set_tuple_id (prefix, isl_dim_out, label);
1221 int n = isl_multi_aff_dim (prefix, isl_dim_in);
1222 isl_union_set *domain = isl_schedule_get_domain (schedule);
1223 isl_multi_union_pw_aff *mupa = outer_projection_mupa (domain, n);
1224 mupa = isl_multi_union_pw_aff_apply_multi_aff (mupa, prefix);
1225 return isl_schedule_insert_partial_schedule (schedule, mupa);
1228 /* Build schedule for the pbb at INDEX. */
1230 static isl_schedule *
1231 build_schedule_pbb (scop_p scop, int *index)
1233 poly_bb_p pbb = scop->pbbs[*index];
1234 ++*index;
1235 isl_set *domain = isl_set_copy (pbb->domain);
1236 isl_union_set *ud = isl_union_set_from_set (domain);
1237 return isl_schedule_from_domain (ud);
1240 static isl_schedule *build_schedule_loop_nest (scop_p, int *, loop_p);
1242 /* Build the schedule of the loop containing the SCOP pbb at INDEX. */
1244 static isl_schedule *
1245 build_schedule_loop (scop_p scop, int *index)
1247 int max = scop->pbbs.length ();
1248 gcc_assert (*index < max);
1249 loop_p loop = loop_at (scop, index);
1251 isl_schedule *s = NULL;
1252 while (nested_in (loop_at (scop, index), loop))
1254 if (loop == loop_at (scop, index))
1255 s = add_in_sequence (s, build_schedule_pbb (scop, index));
1256 else
1257 s = add_in_sequence (s, build_schedule_loop_nest (scop, index, loop));
1259 if (*index == max)
1260 break;
1263 return add_loop_schedule (s, loop, scop);
1266 /* S is the schedule of the loop LOOP. Embed the schedule S in all outer loops.
1267 When CONTEXT_LOOP is null, embed the schedule in all loops contained in the
1268 SCOP surrounding LOOP. When CONTEXT_LOOP is non null, only embed S in the
1269 maximal loop nest contained within CONTEXT_LOOP. */
1271 static isl_schedule *
1272 embed_in_surrounding_loops (__isl_take isl_schedule *s, scop_p scop,
1273 loop_p loop, int *index, loop_p context_loop)
1275 loop_p outer = loop_outer (loop);
1276 sese_l region = scop->scop_info->region;
1277 if (context_loop == outer
1278 || !loop_in_sese_p (outer, region))
1279 return s;
1281 int max = scop->pbbs.length ();
1282 if (*index == max
1283 || (context_loop && !nested_in (loop_at (scop, index), context_loop))
1284 || (!context_loop
1285 && !loop_in_sese_p (find_common_loop (outer, loop_at (scop, index)),
1286 region)))
1287 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop),
1288 scop, outer, index, context_loop);
1290 bool a_pbb;
1291 while ((a_pbb = (outer == loop_at (scop, index)))
1292 || nested_in (loop_at (scop, index), outer))
1294 if (a_pbb)
1295 s = add_in_sequence (s, build_schedule_pbb (scop, index));
1296 else
1297 s = add_in_sequence (s, build_schedule_loop (scop, index));
1299 if (*index == max)
1300 break;
1303 /* We reached the end of the OUTER loop: embed S in OUTER. */
1304 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), scop,
1305 outer, index, context_loop);
1308 /* Build schedule for the full loop nest containing the pbb at INDEX. When
1309 CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP
1310 surrounding the pbb. When CONTEXT_LOOP is non null, only build the maximal loop
1311 nest contained within CONTEXT_LOOP. */
1313 static isl_schedule *
1314 build_schedule_loop_nest (scop_p scop, int *index, loop_p context_loop)
1316 gcc_assert (*index != (int) scop->pbbs.length ());
1318 loop_p loop = loop_at (scop, index);
1319 isl_schedule *s = build_schedule_loop (scop, index);
1320 return embed_in_surrounding_loops (s, scop, loop, index, context_loop);
1323 /* Build the schedule of the SCOP. */
1325 static bool
1326 build_original_schedule (scop_p scop)
1328 int i = 0;
1329 int n = scop->pbbs.length ();
1330 while (i < n)
1332 poly_bb_p pbb = scop->pbbs[i];
1333 isl_schedule *s = NULL;
1334 if (!loop_in_sese_p (pbb_loop (pbb), scop->scop_info->region))
1335 s = build_schedule_pbb (scop, &i);
1336 else
1337 s = build_schedule_loop_nest (scop, &i, NULL);
1339 scop->original_schedule = add_in_sequence (scop->original_schedule, s);
1342 if (dump_file)
1344 fprintf (dump_file, "[sese-to-poly] original schedule:\n");
1345 print_isl_schedule (dump_file, scop->original_schedule);
1347 if (!scop->original_schedule)
1348 return false;
1349 return true;
1352 #endif
1354 /* Builds the polyhedral representation for a SESE region. */
1356 bool
1357 build_poly_scop (scop_p scop)
1359 build_scop_context (scop);
1361 unsigned i = 0;
1362 unsigned n = scop->pbbs.length ();
1363 while (i < n)
1364 i = build_iteration_domains (scop, scop->param_context, i, NULL);
1366 build_scop_drs (scop);
1367 #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
1368 build_original_schedule (scop);
1369 #else
1370 build_scop_scattering (scop);
1371 #endif
1372 return true;
1374 #endif /* HAVE_isl */