2015-11-30 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / graphite-sese-to-poly.c
blobe6802434137dad17f87670fa37ec1c0da4f8efd8
1 /* Conversion of SESE regions to Polyhedra.
2 Copyright (C) 2009-2015 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 /* Since ISL-0.13, the extern is in val_gmp.h. */
60 #if !defined(HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE) && defined(__cplusplus)
61 extern "C" {
62 #endif
63 #include <isl/val_gmp.h>
64 #if !defined(HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE) && defined(__cplusplus)
66 #endif
68 #include "graphite.h"
70 /* Assigns to RES the value of the INTEGER_CST T. */
72 static inline void
73 tree_int_to_gmp (tree t, mpz_t res)
75 wi::to_mpz (t, res, TYPE_SIGN (TREE_TYPE (t)));
78 /* Return an ISL identifier for the polyhedral basic block PBB. */
80 static isl_id *
81 isl_id_for_pbb (scop_p s, poly_bb_p pbb)
83 char name[10];
84 snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
85 return isl_id_alloc (s->isl_context, name, pbb);
88 /* Converts the STATIC_SCHEDULE of PBB into a scattering polyhedron.
89 We generate SCATTERING_DIMENSIONS scattering dimensions.
91 The scattering polyhedron consists of these dimensions: scattering,
92 loop_iterators, parameters.
94 Example:
96 | scattering_dimensions = 5
97 | nb_iterators = 1
98 | scop_nb_params = 2
100 | Schedule:
102 | 4 5
104 | Scattering polyhedron:
106 | scattering: {s1, s2, s3, s4, s5}
107 | loop_iterators: {i}
108 | parameters: {p1, p2}
110 | s1 s2 s3 s4 s5 i p1 p2 1
111 | 1 0 0 0 0 0 0 0 -4 = 0
112 | 0 1 0 0 0 -1 0 0 0 = 0
113 | 0 0 1 0 0 0 0 0 -5 = 0 */
115 static void
116 build_pbb_scattering_polyhedrons (isl_aff *static_sched,
117 poly_bb_p pbb)
119 isl_val *val;
121 int scattering_dimensions = isl_set_dim (pbb->domain, isl_dim_set) * 2 + 1;
123 isl_space *dc = isl_set_get_space (pbb->domain);
124 isl_space *dm = isl_space_add_dims (isl_space_from_domain (dc),
125 isl_dim_out, scattering_dimensions);
126 pbb->schedule = isl_map_universe (dm);
128 for (int i = 0; i < scattering_dimensions; i++)
130 /* Textual order inside this loop. */
131 if ((i % 2) == 0)
133 isl_constraint *c = isl_equality_alloc
134 (isl_local_space_from_space (isl_map_get_space (pbb->schedule)));
136 val = isl_aff_get_coefficient_val (static_sched, isl_dim_in, i / 2);
137 gcc_assert (val && isl_val_is_int (val));
139 val = isl_val_neg (val);
140 c = isl_constraint_set_constant_val (c, val);
141 c = isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1);
142 pbb->schedule = isl_map_add_constraint (pbb->schedule, c);
145 /* Iterations of this loop. */
146 else /* if ((i % 2) == 1) */
148 int loop = (i - 1) / 2;
149 pbb->schedule = isl_map_equate (pbb->schedule, isl_dim_in, loop,
150 isl_dim_out, i);
154 pbb->transformed = isl_map_copy (pbb->schedule);
157 /* Build for BB the static schedule.
159 The static schedule is a Dewey numbering of the abstract syntax
160 tree: http://en.wikipedia.org/wiki/Dewey_Decimal_Classification
162 The following example informally defines the static schedule:
165 for (i: ...)
167 for (j: ...)
173 for (k: ...)
181 Static schedules for A to F:
183 DEPTH
184 0 1 2
186 B 1 0 0
187 C 1 0 1
188 D 1 1 0
189 E 1 1 1
193 static void
194 build_scop_scattering (scop_p scop)
196 gimple_poly_bb_p previous_gbb = NULL;
197 isl_space *dc = isl_set_get_space (scop->param_context);
198 isl_aff *static_sched;
200 dc = isl_space_add_dims (dc, isl_dim_set, number_of_loops (cfun));
201 static_sched = isl_aff_zero_on_domain (isl_local_space_from_space (dc));
203 /* We have to start schedules at 0 on the first component and
204 because we cannot compare_prefix_loops against a previous loop,
205 prefix will be equal to zero, and that index will be
206 incremented before copying. */
207 static_sched = isl_aff_add_coefficient_si (static_sched, isl_dim_in, 0, -1);
209 int i;
210 poly_bb_p pbb;
211 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
213 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
214 int prefix = 0;
216 if (previous_gbb)
217 prefix = nb_common_loops (scop->scop_info->region, previous_gbb, gbb);
219 previous_gbb = gbb;
221 static_sched = isl_aff_add_coefficient_si (static_sched, isl_dim_in,
222 prefix, 1);
223 build_pbb_scattering_polyhedrons (static_sched, pbb);
226 isl_aff_free (static_sched);
229 static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space);
231 /* Extract an affine expression from the chain of recurrence E. */
233 static isl_pw_aff *
234 extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space)
236 isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space));
237 isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space));
238 isl_local_space *ls = isl_local_space_from_space (space);
239 unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)) - 1;
240 isl_aff *loop = isl_aff_set_coefficient_si
241 (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1);
242 isl_pw_aff *l = isl_pw_aff_from_aff (loop);
244 /* Before multiplying, make sure that the result is affine. */
245 gcc_assert (isl_pw_aff_is_cst (rhs)
246 || isl_pw_aff_is_cst (l));
248 return isl_pw_aff_add (lhs, isl_pw_aff_mul (rhs, l));
251 /* Extract an affine expression from the mult_expr E. */
253 static isl_pw_aff *
254 extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space)
256 isl_pw_aff *lhs = extract_affine (s, TREE_OPERAND (e, 0),
257 isl_space_copy (space));
258 isl_pw_aff *rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
260 if (!isl_pw_aff_is_cst (lhs)
261 && !isl_pw_aff_is_cst (rhs))
263 isl_pw_aff_free (lhs);
264 isl_pw_aff_free (rhs);
265 return NULL;
268 return isl_pw_aff_mul (lhs, rhs);
271 /* Return an ISL identifier from the name of the ssa_name E. */
273 static isl_id *
274 isl_id_for_ssa_name (scop_p s, tree e)
276 const char *name = get_name (e);
277 isl_id *id;
279 if (name)
280 id = isl_id_alloc (s->isl_context, name, e);
281 else
283 char name1[10];
284 snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e));
285 id = isl_id_alloc (s->isl_context, name1, e);
288 return id;
291 /* Return an ISL identifier for the data reference DR. Data references and
292 scalar references get the same isl_id. They need to be comparable and are
293 distinguished through the first dimension, which contains the alias set or
294 SSA_NAME_VERSION number. */
296 static isl_id *
297 isl_id_for_dr (scop_p s)
299 return isl_id_alloc (s->isl_context, "", 0);
302 /* Extract an affine expression from the ssa_name E. */
304 static isl_pw_aff *
305 extract_affine_name (scop_p s, tree e, __isl_take isl_space *space)
307 isl_id *id = isl_id_for_ssa_name (s, e);
308 int dimension = isl_space_find_dim_by_id (space, isl_dim_param, id);
309 isl_id_free (id);
310 isl_set *dom = isl_set_universe (isl_space_copy (space));
311 isl_aff *aff = isl_aff_zero_on_domain (isl_local_space_from_space (space));
312 aff = isl_aff_add_coefficient_si (aff, isl_dim_param, dimension, 1);
313 return isl_pw_aff_alloc (dom, aff);
316 /* Extract an affine expression from the gmp constant G. */
318 static isl_pw_aff *
319 extract_affine_gmp (mpz_t g, __isl_take isl_space *space)
321 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
322 isl_aff *aff = isl_aff_zero_on_domain (ls);
323 isl_set *dom = isl_set_universe (space);
324 isl_ctx *ct = isl_aff_get_ctx (aff);
325 isl_val *v = isl_val_int_from_gmp (ct, g);
326 aff = isl_aff_add_constant_val (aff, v);
328 return isl_pw_aff_alloc (dom, aff);
331 /* Extract an affine expression from the integer_cst E. */
333 static isl_pw_aff *
334 extract_affine_int (tree e, __isl_take isl_space *space)
336 mpz_t g;
338 mpz_init (g);
339 tree_int_to_gmp (e, g);
340 isl_pw_aff *res = extract_affine_gmp (g, space);
341 mpz_clear (g);
343 return res;
346 /* Compute pwaff mod 2^width. */
348 static isl_pw_aff *
349 wrap (isl_pw_aff *pwaff, unsigned width)
351 isl_val *mod;
353 mod = isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff), width);
354 mod = isl_val_2exp (mod);
355 pwaff = isl_pw_aff_mod_val (pwaff, mod);
357 return pwaff;
360 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
361 Otherwise returns -1. */
363 static inline int
364 parameter_index_in_region_1 (tree name, sese_info_p region)
366 int i;
367 tree p;
369 gcc_assert (TREE_CODE (name) == SSA_NAME);
371 FOR_EACH_VEC_ELT (region->params, i, p)
372 if (p == name)
373 return i;
375 return -1;
378 /* Extract an affine expression from the tree E in the scop S. */
380 static isl_pw_aff *
381 extract_affine (scop_p s, tree e, __isl_take isl_space *space)
383 isl_pw_aff *lhs, *rhs, *res;
385 if (e == chrec_dont_know) {
386 isl_space_free (space);
387 return NULL;
390 switch (TREE_CODE (e))
392 case POLYNOMIAL_CHREC:
393 res = extract_affine_chrec (s, e, space);
394 break;
396 case MULT_EXPR:
397 res = extract_affine_mul (s, e, space);
398 break;
400 case PLUS_EXPR:
401 case POINTER_PLUS_EXPR:
402 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
403 rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
404 res = isl_pw_aff_add (lhs, rhs);
405 break;
407 case MINUS_EXPR:
408 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
409 rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
410 res = isl_pw_aff_sub (lhs, rhs);
411 break;
413 case NEGATE_EXPR:
414 case BIT_NOT_EXPR:
415 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
416 rhs = extract_affine (s, integer_minus_one_node, space);
417 res = isl_pw_aff_mul (lhs, rhs);
418 break;
420 case SSA_NAME:
421 gcc_assert (-1 != parameter_index_in_region_1 (e, s->scop_info)
422 || !invariant_in_sese_p_rec (e, s->scop_info->region, NULL));
423 res = extract_affine_name (s, e, space);
424 break;
426 case INTEGER_CST:
427 res = extract_affine_int (e, space);
428 /* No need to wrap a single integer. */
429 return res;
431 CASE_CONVERT:
432 case NON_LVALUE_EXPR:
433 res = extract_affine (s, TREE_OPERAND (e, 0), space);
434 break;
436 default:
437 gcc_unreachable ();
438 break;
441 tree type = TREE_TYPE (e);
442 if (TYPE_UNSIGNED (type))
443 res = wrap (res, TYPE_PRECISION (type));
445 return res;
448 /* Assign dimension for each parameter in SCOP. */
450 static void
451 set_scop_parameter_dim (scop_p scop)
453 sese_info_p region = scop->scop_info;
454 unsigned nbp = sese_nb_params (region);
455 isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0);
457 unsigned i;
458 tree e;
459 FOR_EACH_VEC_ELT (region->params, i, e)
460 space = isl_space_set_dim_id (space, isl_dim_param, i,
461 isl_id_for_ssa_name (scop, e));
463 scop->param_context = isl_set_universe (space);
466 static inline bool
467 cleanup_loop_iter_dom (isl_set *inner, isl_set *outer, isl_space *space, mpz_t g)
469 isl_set_free (inner);
470 isl_set_free (outer);
471 isl_space_free (space);
472 mpz_clear (g);
473 return false;
476 /* Builds the constraint polyhedra for LOOP in SCOP. OUTER_PH gives
477 the constraints for the surrounding loops. */
479 static bool
480 build_loop_iteration_domains (scop_p scop, struct loop *loop,
481 int nb,
482 isl_set *outer, isl_set **doms)
485 tree nb_iters = number_of_latch_executions (loop);
486 sese_l region = scop->scop_info->region;
487 gcc_assert (loop_in_sese_p (loop, region));
489 isl_set *inner = isl_set_copy (outer);
490 int pos = isl_set_dim (outer, isl_dim_set);
491 isl_val *v;
492 mpz_t g;
494 mpz_init (g);
496 inner = isl_set_add_dims (inner, isl_dim_set, 1);
497 isl_space *space = isl_set_get_space (inner);
499 /* 0 <= loop_i */
500 isl_constraint *c = isl_inequality_alloc
501 (isl_local_space_from_space (isl_space_copy (space)));
502 c = isl_constraint_set_coefficient_si (c, isl_dim_set, pos, 1);
503 inner = isl_set_add_constraint (inner, c);
505 /* loop_i <= cst_nb_iters */
506 if (TREE_CODE (nb_iters) == INTEGER_CST)
508 c = isl_inequality_alloc
509 (isl_local_space_from_space (isl_space_copy (space)));
510 c = isl_constraint_set_coefficient_si (c, isl_dim_set, pos, -1);
511 tree_int_to_gmp (nb_iters, g);
512 v = isl_val_int_from_gmp (scop->isl_context, g);
513 c = isl_constraint_set_constant_val (c, v);
514 inner = isl_set_add_constraint (inner, c);
517 /* loop_i <= expr_nb_iters */
518 else if (!chrec_contains_undetermined (nb_iters))
520 isl_pw_aff *aff;
522 nb_iters = scalar_evolution_in_region (region, loop, nb_iters);
524 /* Bail out as we do not know the scev. */
525 if (chrec_contains_undetermined (nb_iters))
526 return cleanup_loop_iter_dom (inner, outer, space, g);
528 aff = extract_affine (scop, nb_iters, isl_set_get_space (inner));
529 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff));
530 valid = isl_set_project_out (valid, isl_dim_set, 0,
531 isl_set_dim (valid, isl_dim_set));
533 if (valid)
534 scop->param_context = isl_set_intersect (scop->param_context, valid);
536 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
537 isl_aff *al = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls),
538 isl_dim_in, pos, 1);
539 isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (al),
540 isl_pw_aff_copy (aff));
541 inner = isl_set_intersect (inner, le);
543 widest_int nit;
544 if (max_stmt_executions (loop, &nit))
546 /* Insert in the context the constraints from the
547 estimation of the number of iterations NIT and the
548 symbolic number of iterations (involving parameter
549 names) NB_ITERS. First, build the affine expression
550 "NIT - NB_ITERS" and then say that it is positive,
551 i.e., NIT approximates NB_ITERS: "NIT >= NB_ITERS". */
552 mpz_t g;
553 mpz_init (g);
554 wi::to_mpz (nit, g, SIGNED);
555 mpz_sub_ui (g, g, 1);
557 isl_pw_aff *approx
558 = extract_affine_gmp (g, isl_set_get_space (inner));
559 isl_set *x = isl_pw_aff_ge_set (approx, aff);
560 x = isl_set_project_out (x, isl_dim_set, 0,
561 isl_set_dim (x, isl_dim_set));
562 scop->param_context = isl_set_intersect (scop->param_context, x);
564 isl_constraint *c = isl_inequality_alloc
565 (isl_local_space_from_space (isl_space_copy (space)));
566 c = isl_constraint_set_coefficient_si (c, isl_dim_set, pos, -1);
567 v = isl_val_int_from_gmp (scop->isl_context, g);
568 mpz_clear (g);
569 c = isl_constraint_set_constant_val (c, v);
570 inner = isl_set_add_constraint (inner, c);
572 else
573 isl_pw_aff_free (aff);
575 else
576 gcc_unreachable ();
578 if (loop->inner
579 && !build_loop_iteration_domains (scop, loop->inner, nb + 1,
580 isl_set_copy (inner), doms))
581 return cleanup_loop_iter_dom (inner, outer, space, g);
583 if (nb != 0
584 && loop->next
585 && loop_in_sese_p (loop->next, region)
586 && !build_loop_iteration_domains (scop, loop->next, nb,
587 isl_set_copy (outer), doms))
588 return cleanup_loop_iter_dom (inner, outer, space, g);
590 doms[loop->num] = inner;
592 isl_set_free (outer);
593 isl_space_free (space);
594 mpz_clear (g);
595 return true;
598 /* Returns a linear expression for tree T evaluated in PBB. */
600 static isl_pw_aff *
601 create_pw_aff_from_tree (poly_bb_p pbb, tree t)
603 scop_p scop = PBB_SCOP (pbb);
605 t = scalar_evolution_in_region (scop->scop_info->region, pbb_loop (pbb), t);
607 /* Bail out as we do not know the scev. */
608 if (chrec_contains_undetermined (t))
609 return NULL;
611 gcc_assert (!automatically_generated_chrec_p (t));
613 return extract_affine (scop, t, isl_set_get_space (pbb->domain));
616 /* Add conditional statement STMT to pbb. CODE is used as the comparison
617 operator. This allows us to invert the condition or to handle
618 inequalities. */
620 static bool
621 add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code)
623 isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, gimple_cond_lhs (stmt));
624 if (!lhs)
625 return false;
627 isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, gimple_cond_rhs (stmt));
628 if (!rhs)
630 isl_pw_aff_free (lhs);
631 return false;
634 isl_set *cond;
635 switch (code)
637 case LT_EXPR:
638 cond = isl_pw_aff_lt_set (lhs, rhs);
639 break;
641 case GT_EXPR:
642 cond = isl_pw_aff_gt_set (lhs, rhs);
643 break;
645 case LE_EXPR:
646 cond = isl_pw_aff_le_set (lhs, rhs);
647 break;
649 case GE_EXPR:
650 cond = isl_pw_aff_ge_set (lhs, rhs);
651 break;
653 case EQ_EXPR:
654 cond = isl_pw_aff_eq_set (lhs, rhs);
655 break;
657 case NE_EXPR:
658 cond = isl_pw_aff_ne_set (lhs, rhs);
659 break;
661 default:
662 isl_pw_aff_free (lhs);
663 isl_pw_aff_free (rhs);
664 return true;
667 cond = isl_set_coalesce (cond);
668 cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain));
669 pbb->domain = isl_set_intersect (pbb->domain, cond);
670 return true;
673 /* Add conditions to the domain of PBB. */
675 static bool
676 add_conditions_to_domain (poly_bb_p pbb)
678 unsigned int i;
679 gimple *stmt;
680 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
682 if (GBB_CONDITIONS (gbb).is_empty ())
683 return true;
685 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
686 switch (gimple_code (stmt))
688 case GIMPLE_COND:
690 /* Don't constrain on anything else than INTEGER_TYPE. */
691 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt))) != INTEGER_TYPE)
692 break;
694 gcond *cond_stmt = as_a <gcond *> (stmt);
695 enum tree_code code = gimple_cond_code (cond_stmt);
697 /* The conditions for ELSE-branches are inverted. */
698 if (!GBB_CONDITION_CASES (gbb)[i])
699 code = invert_tree_comparison (code, false);
701 if (!add_condition_to_pbb (pbb, cond_stmt, code))
702 return false;
703 break;
706 case GIMPLE_SWITCH:
707 /* Switch statements are not supported right now - fall through. */
709 default:
710 gcc_unreachable ();
711 break;
714 return true;
717 /* Traverses all the GBBs of the SCOP and add their constraints to the
718 iteration domains. */
720 static bool
721 add_conditions_to_constraints (scop_p scop)
723 int i;
724 poly_bb_p pbb;
726 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
727 if (!add_conditions_to_domain (pbb))
728 return false;
730 return true;
733 /* Add constraints on the possible values of parameter P from the type
734 of P. */
736 static void
737 add_param_constraints (scop_p scop, graphite_dim_t p)
739 tree parameter = scop->scop_info->params[p];
740 tree type = TREE_TYPE (parameter);
741 tree lb = NULL_TREE;
742 tree ub = NULL_TREE;
744 if (POINTER_TYPE_P (type) || !TYPE_MIN_VALUE (type))
745 lb = lower_bound_in_type (type, type);
746 else
747 lb = TYPE_MIN_VALUE (type);
749 if (POINTER_TYPE_P (type) || !TYPE_MAX_VALUE (type))
750 ub = upper_bound_in_type (type, type);
751 else
752 ub = TYPE_MAX_VALUE (type);
754 if (lb)
756 isl_space *space = isl_set_get_space (scop->param_context);
757 isl_constraint *c;
758 mpz_t g;
759 isl_val *v;
761 c = isl_inequality_alloc (isl_local_space_from_space (space));
762 mpz_init (g);
763 tree_int_to_gmp (lb, g);
764 v = isl_val_int_from_gmp (scop->isl_context, g);
765 v = isl_val_neg (v);
766 mpz_clear (g);
767 c = isl_constraint_set_constant_val (c, v);
768 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, 1);
770 scop->param_context = isl_set_add_constraint (scop->param_context, c);
773 if (ub)
775 isl_space *space = isl_set_get_space (scop->param_context);
776 isl_constraint *c;
777 mpz_t g;
778 isl_val *v;
780 c = isl_inequality_alloc (isl_local_space_from_space (space));
782 mpz_init (g);
783 tree_int_to_gmp (ub, g);
784 v = isl_val_int_from_gmp (scop->isl_context, g);
785 mpz_clear (g);
786 c = isl_constraint_set_constant_val (c, v);
787 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, -1);
789 scop->param_context = isl_set_add_constraint (scop->param_context, c);
793 /* Build the context of the SCOP. The context usually contains extra
794 constraints that are added to the iteration domains that constrain
795 some parameters. */
797 static void
798 build_scop_context (scop_p scop)
800 graphite_dim_t p, n = scop_nb_params (scop);
802 for (p = 0; p < n; p++)
803 add_param_constraints (scop, p);
806 /* Build the iteration domains: the loops belonging to the current
807 SCOP, and that vary for the execution of the current basic block.
808 Returns false if there is no loop in SCOP. */
810 static bool
811 build_scop_iteration_domain (scop_p scop)
813 sese_info_p region = scop->scop_info;
814 int nb_loops = number_of_loops (cfun);
815 isl_set **doms = XCNEWVEC (isl_set *, nb_loops);
816 bool res = true;
817 int i;
818 struct loop *loop;
819 FOR_EACH_VEC_ELT (region->loop_nest, i, loop)
820 if (!loop_in_sese_p (loop_outer (loop), region->region)
821 && !build_loop_iteration_domains (scop, loop, 0,
822 isl_set_copy (scop->param_context), doms))
824 res = false;
825 goto cleanup;
828 poly_bb_p pbb;
829 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
831 loop = pbb_loop (pbb);
833 if (doms[loop->num])
834 pbb->domain = isl_set_copy (doms[loop->num]);
835 else
836 pbb->domain = isl_set_copy (scop->param_context);
838 pbb->domain = isl_set_set_tuple_id (pbb->domain,
839 isl_id_for_pbb (scop, pbb));
842 cleanup:
843 for (int i = 0; i < nb_loops; i++)
844 if (doms[i])
845 isl_set_free (doms[i]);
847 free (doms);
848 return res;
851 /* Add a constrain to the ACCESSES polyhedron for the alias set of
852 data reference DR. ACCESSP_NB_DIMS is the dimension of the
853 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
854 domain. */
856 static isl_map *
857 pdr_add_alias_set (isl_map *acc, dr_info &dri)
859 isl_constraint *c = isl_equality_alloc
860 (isl_local_space_from_space (isl_map_get_space (acc)));
861 /* Positive numbers for all alias sets. */
862 c = isl_constraint_set_constant_si (c, -dri.alias_set);
863 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
865 return isl_map_add_constraint (acc, c);
868 /* Add a constrain to the ACCESSES polyhedron for the alias set of
869 data reference DR. ACCESSP_NB_DIMS is the dimension of the
870 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
871 domain. */
873 static isl_map *
874 add_scalar_version_numbers (isl_map *acc, tree var)
876 isl_constraint *c = isl_equality_alloc
877 (isl_local_space_from_space (isl_map_get_space (acc)));
878 int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP);
879 /* Each scalar variables has a unique alias set number starting from
880 max_arrays. */
881 c = isl_constraint_set_constant_si (c, -max_arrays - SSA_NAME_VERSION (var));
882 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
884 return isl_map_add_constraint (acc, c);
887 /* Assign the affine expression INDEX to the output dimension POS of
888 MAP and return the result. */
890 static isl_map *
891 set_index (isl_map *map, int pos, isl_pw_aff *index)
893 isl_map *index_map;
894 int len = isl_map_dim (map, isl_dim_out);
895 isl_id *id;
897 index_map = isl_map_from_pw_aff (index);
898 index_map = isl_map_insert_dims (index_map, isl_dim_out, 0, pos);
899 index_map = isl_map_add_dims (index_map, isl_dim_out, len - pos - 1);
901 id = isl_map_get_tuple_id (map, isl_dim_out);
902 index_map = isl_map_set_tuple_id (index_map, isl_dim_out, id);
903 id = isl_map_get_tuple_id (map, isl_dim_in);
904 index_map = isl_map_set_tuple_id (index_map, isl_dim_in, id);
906 return isl_map_intersect (map, index_map);
909 /* Add to ACCESSES polyhedron equalities defining the access functions
910 to the memory. ACCESSP_NB_DIMS is the dimension of the ACCESSES
911 polyhedron, DOM_NB_DIMS is the dimension of the iteration domain.
912 PBB is the poly_bb_p that contains the data reference DR. */
914 static isl_map *
915 pdr_add_memory_accesses (isl_map *acc, dr_info &dri)
917 data_reference_p dr = dri.dr;
918 poly_bb_p pbb = dri.pbb;
919 int i, nb_subscripts = DR_NUM_DIMENSIONS (dr);
920 scop_p scop = PBB_SCOP (pbb);
922 for (i = 0; i < nb_subscripts; i++)
924 isl_pw_aff *aff;
925 tree afn = DR_ACCESS_FN (dr, nb_subscripts - 1 - i);
927 aff = extract_affine (scop, afn,
928 isl_space_domain (isl_map_get_space (acc)));
929 acc = set_index (acc, i + 1, aff);
932 return acc;
935 /* Add constrains representing the size of the accessed data to the
936 ACCESSES polyhedron. ACCESSP_NB_DIMS is the dimension of the
937 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
938 domain. */
940 static isl_set *
941 pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop,
942 data_reference_p dr)
944 tree ref = DR_REF (dr);
946 int nb_subscripts = DR_NUM_DIMENSIONS (dr);
947 for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0))
949 if (TREE_CODE (ref) != ARRAY_REF)
950 return subscript_sizes;
952 tree low = array_ref_low_bound (ref);
953 tree high = array_ref_up_bound (ref);
955 /* XXX The PPL code dealt separately with
956 subscript - low >= 0 and high - subscript >= 0 in case one of
957 the two bounds isn't known. Do the same here? */
959 if (tree_fits_shwi_p (low)
960 && high
961 && tree_fits_shwi_p (high)
962 /* 1-element arrays at end of structures may extend over
963 their declared size. */
964 && !(array_at_struct_end_p (ref)
965 && operand_equal_p (low, high, 0)))
967 isl_id *id;
968 isl_aff *aff;
969 isl_set *univ, *lbs, *ubs;
970 isl_pw_aff *index;
971 isl_set *valid;
972 isl_space *space = isl_set_get_space (subscript_sizes);
973 isl_pw_aff *lb = extract_affine_int (low, isl_space_copy (space));
974 isl_pw_aff *ub = extract_affine_int (high, isl_space_copy (space));
976 /* high >= 0 */
977 valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub));
978 valid = isl_set_project_out (valid, isl_dim_set, 0,
979 isl_set_dim (valid, isl_dim_set));
980 scop->param_context = isl_set_intersect (scop->param_context, valid);
982 aff = isl_aff_zero_on_domain (isl_local_space_from_space (space));
983 aff = isl_aff_add_coefficient_si (aff, isl_dim_in, i + 1, 1);
984 univ = isl_set_universe (isl_space_domain (isl_aff_get_space (aff)));
985 index = isl_pw_aff_alloc (univ, aff);
987 id = isl_set_get_tuple_id (subscript_sizes);
988 lb = isl_pw_aff_set_tuple_id (lb, isl_dim_in, isl_id_copy (id));
989 ub = isl_pw_aff_set_tuple_id (ub, isl_dim_in, id);
991 /* low <= sub_i <= high */
992 lbs = isl_pw_aff_ge_set (isl_pw_aff_copy (index), lb);
993 ubs = isl_pw_aff_le_set (index, ub);
994 subscript_sizes = isl_set_intersect (subscript_sizes, lbs);
995 subscript_sizes = isl_set_intersect (subscript_sizes, ubs);
999 return subscript_sizes;
1002 /* Build data accesses for DRI. */
1004 static void
1005 build_poly_dr (dr_info &dri)
1007 isl_map *acc;
1008 isl_set *subscript_sizes;
1009 poly_bb_p pbb = dri.pbb;
1010 data_reference_p dr = dri.dr;
1011 scop_p scop = PBB_SCOP (pbb);
1012 isl_id *id = isl_id_for_dr (scop);
1015 isl_space *dc = isl_set_get_space (pbb->domain);
1016 int nb_out = 1 + DR_NUM_DIMENSIONS (dr);
1017 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
1018 isl_dim_out, nb_out);
1020 acc = isl_map_universe (space);
1021 acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id));
1024 acc = pdr_add_alias_set (acc, dri);
1025 acc = pdr_add_memory_accesses (acc, dri);
1028 int nb = 1 + DR_NUM_DIMENSIONS (dr);
1029 isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb);
1031 space = isl_space_set_tuple_id (space, isl_dim_set, id);
1032 subscript_sizes = isl_set_nat_universe (space);
1033 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
1034 dri.alias_set);
1035 subscript_sizes = pdr_add_data_dimensions (subscript_sizes, scop, dr);
1038 new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE,
1039 acc, subscript_sizes);
1042 static void
1043 build_poly_sr_1 (poly_bb_p pbb, gimple *stmt, tree var, enum poly_dr_type kind,
1044 isl_map *acc, isl_set *subscript_sizes)
1046 int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP);
1047 /* Each scalar variables has a unique alias set number starting from
1048 max_arrays. */
1049 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
1050 max_arrays + SSA_NAME_VERSION (var));
1052 new_poly_dr (pbb, stmt, kind, add_scalar_version_numbers (acc, var),
1053 subscript_sizes);
1056 /* Record all cross basic block scalar variables in PBB. */
1058 static void
1059 build_poly_sr (poly_bb_p pbb)
1061 scop_p scop = PBB_SCOP (pbb);
1062 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
1063 vec<scalar_use> reads = gbb->read_scalar_refs;
1064 vec<tree> writes = gbb->write_scalar_refs;
1066 isl_space *dc = isl_set_get_space (pbb->domain);
1067 int nb_out = 1;
1068 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
1069 isl_dim_out, nb_out);
1070 isl_id *id = isl_id_for_dr (scop);
1071 space = isl_space_set_tuple_id (space, isl_dim_set, isl_id_copy (id));
1072 isl_map *acc = isl_map_universe (isl_space_copy (space));
1073 acc = isl_map_set_tuple_id (acc, isl_dim_out, id);
1074 isl_set *subscript_sizes = isl_set_nat_universe (space);
1076 int i;
1077 tree var;
1078 FOR_EACH_VEC_ELT (writes, i, var)
1079 build_poly_sr_1 (pbb, SSA_NAME_DEF_STMT (var), var, PDR_WRITE,
1080 isl_map_copy (acc), isl_set_copy (subscript_sizes));
1082 scalar_use *use;
1083 FOR_EACH_VEC_ELT (reads, i, use)
1084 build_poly_sr_1 (pbb, use->first, use->second, PDR_READ, isl_map_copy (acc),
1085 isl_set_copy (subscript_sizes));
1087 isl_map_free (acc);
1088 isl_set_free (subscript_sizes);
1091 /* Build data references in SCOP. */
1093 static void
1094 build_scop_drs (scop_p scop)
1096 int i;
1097 dr_info *dri;
1098 FOR_EACH_VEC_ELT (scop->drs, i, dri)
1099 build_poly_dr (*dri);
1101 poly_bb_p pbb;
1102 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
1103 build_poly_sr (pbb);
1106 /* Builds the polyhedral representation for a SESE region. */
1108 bool
1109 build_poly_scop (scop_p scop)
1111 set_scop_parameter_dim (scop);
1112 if (!build_scop_iteration_domain (scop))
1113 return false;
1115 build_scop_context (scop);
1117 if (!add_conditions_to_constraints (scop))
1118 return false;
1120 build_scop_drs (scop);
1121 build_scop_scattering (scop);
1122 return true;
1124 #endif /* HAVE_isl */