]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/graphite-sese-to-poly.c
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / graphite-sese-to-poly.c
CommitLineData
2abae5f1 1/* Conversion of SESE regions to Polyhedra.
99dee823 2 Copyright (C) 2009-2021 Free Software Foundation, Inc.
2abae5f1
SP
3 Contributed by Sebastian Pop <sebastian.pop@amd.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
deda4625 21#define INCLUDE_ISL
4d776011 22
2abae5f1 23#include "config.h"
33ad93b9 24
eae1a5d4 25#ifdef HAVE_isl
33ad93b9 26
2abae5f1
SP
27#include "system.h"
28#include "coretypes.h"
c7131fb2 29#include "backend.h"
9fdcd34e 30#include "cfghooks.h"
40e23961 31#include "tree.h"
c7131fb2 32#include "gimple.h"
c7131fb2 33#include "ssa.h"
40e23961 34#include "fold-const.h"
5be5c238 35#include "gimple-iterator.h"
18f429e2
AM
36#include "gimplify.h"
37#include "gimplify-me.h"
442b4905 38#include "tree-cfg.h"
e28030cf
AM
39#include "tree-ssa-loop-manip.h"
40#include "tree-ssa-loop-niter.h"
442b4905
AM
41#include "tree-ssa-loop.h"
42#include "tree-into-ssa.h"
7a1c57d3 43#include "tree-pass.h"
2abae5f1 44#include "cfgloop.h"
2abae5f1
SP
45#include "tree-data-ref.h"
46#include "tree-scalar-evolution.h"
2abae5f1 47#include "domwalk.h"
9c358739 48#include "tree-ssa-propagate.h"
cf98f0f4 49#include "graphite.h"
2abae5f1 50
e357a5e0 51/* Return an isl identifier for the polyhedral basic block PBB. */
33ad93b9
RG
52
53static isl_id *
54isl_id_for_pbb (scop_p s, poly_bb_p pbb)
55{
efcc8d38 56 char name[14];
33ad93b9 57 snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
8e4dc590 58 return isl_id_alloc (s->isl_context, name, pbb);
33ad93b9
RG
59}
60
33ad93b9
RG
61static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space);
62
63/* Extract an affine expression from the chain of recurrence E. */
2abae5f1 64
33ad93b9
RG
65static isl_pw_aff *
66extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space)
67{
68 isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space));
69 isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space));
70 isl_local_space *ls = isl_local_space_from_space (space);
a68f286c 71 unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)) - 1;
33ad93b9
RG
72 isl_aff *loop = isl_aff_set_coefficient_si
73 (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1);
74 isl_pw_aff *l = isl_pw_aff_from_aff (loop);
75
76 /* Before multiplying, make sure that the result is affine. */
77 gcc_assert (isl_pw_aff_is_cst (rhs)
78 || isl_pw_aff_is_cst (l));
79
80 return isl_pw_aff_add (lhs, isl_pw_aff_mul (rhs, l));
81}
82
83/* Extract an affine expression from the mult_expr E. */
84
85static isl_pw_aff *
86extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space)
87{
88 isl_pw_aff *lhs = extract_affine (s, TREE_OPERAND (e, 0),
89 isl_space_copy (space));
90 isl_pw_aff *rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
2abae5f1 91
33ad93b9
RG
92 if (!isl_pw_aff_is_cst (lhs)
93 && !isl_pw_aff_is_cst (rhs))
94 {
95 isl_pw_aff_free (lhs);
96 isl_pw_aff_free (rhs);
97 return NULL;
2abae5f1
SP
98 }
99
33ad93b9 100 return isl_pw_aff_mul (lhs, rhs);
2abae5f1
SP
101}
102
e357a5e0 103/* Return an isl identifier from the name of the ssa_name E. */
2abae5f1 104
33ad93b9
RG
105static isl_id *
106isl_id_for_ssa_name (scop_p s, tree e)
2abae5f1 107{
efcc8d38 108 char name1[14];
49385686
AK
109 snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e));
110 return isl_id_alloc (s->isl_context, name1, e);
33ad93b9 111}
2abae5f1 112
e357a5e0 113/* Return an isl identifier for the data reference DR. Data references and
65b016eb
AK
114 scalar references get the same isl_id. They need to be comparable and are
115 distinguished through the first dimension, which contains the alias set or
116 SSA_NAME_VERSION number. */
2abae5f1 117
33ad93b9 118static isl_id *
65b016eb 119isl_id_for_dr (scop_p s)
33ad93b9 120{
8e4dc590 121 return isl_id_alloc (s->isl_context, "", 0);
2abae5f1
SP
122}
123
33ad93b9 124/* Extract an affine expression from the ssa_name E. */
2abae5f1 125
33ad93b9 126static isl_pw_aff *
30c4440c 127extract_affine_name (int dimension, __isl_take isl_space *space)
2abae5f1 128{
8e4dc590
AK
129 isl_set *dom = isl_set_universe (isl_space_copy (space));
130 isl_aff *aff = isl_aff_zero_on_domain (isl_local_space_from_space (space));
33ad93b9
RG
131 aff = isl_aff_add_coefficient_si (aff, isl_dim_param, dimension, 1);
132 return isl_pw_aff_alloc (dom, aff);
133}
2abae5f1 134
cc46a51d
RB
135/* Convert WI to a isl_val with CTX. */
136
137static __isl_give isl_val *
138isl_val_int_from_wi (isl_ctx *ctx, const widest_int &wi)
139{
140 if (wi::neg_p (wi, SIGNED))
141 {
142 widest_int mwi = -wi;
143 return isl_val_neg (isl_val_int_from_chunks (ctx, mwi.get_len (),
144 sizeof (HOST_WIDE_INT),
145 mwi.get_val ()));
146 }
147 return isl_val_int_from_chunks (ctx, wi.get_len (), sizeof (HOST_WIDE_INT),
148 wi.get_val ());
149}
150
33ad93b9 151/* Extract an affine expression from the gmp constant G. */
2abae5f1 152
33ad93b9 153static isl_pw_aff *
cc46a51d 154extract_affine_wi (const widest_int &g, __isl_take isl_space *space)
33ad93b9
RG
155{
156 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
157 isl_aff *aff = isl_aff_zero_on_domain (ls);
158 isl_set *dom = isl_set_universe (space);
8e4dc590 159 isl_ctx *ct = isl_aff_get_ctx (aff);
cc46a51d 160 isl_val *v = isl_val_int_from_wi (ct, g);
b47595f7 161 aff = isl_aff_add_constant_val (aff, v);
2abae5f1 162
33ad93b9 163 return isl_pw_aff_alloc (dom, aff);
2abae5f1
SP
164}
165
33ad93b9 166/* Extract an affine expression from the integer_cst E. */
2abae5f1 167
33ad93b9
RG
168static isl_pw_aff *
169extract_affine_int (tree e, __isl_take isl_space *space)
170{
cc46a51d 171 isl_pw_aff *res = extract_affine_wi (wi::to_widest (e), space);
33ad93b9
RG
172 return res;
173}
174
175/* Compute pwaff mod 2^width. */
176
177static isl_pw_aff *
178wrap (isl_pw_aff *pwaff, unsigned width)
2abae5f1 179{
b47595f7 180 isl_val *mod;
2abae5f1 181
24757752 182 mod = isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff), width);
b47595f7
MN
183 mod = isl_val_2exp (mod);
184 pwaff = isl_pw_aff_mod_val (pwaff, mod);
33ad93b9
RG
185
186 return pwaff;
2abae5f1
SP
187}
188
2abae5f1
SP
189/* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
190 Otherwise returns -1. */
191
192static inline int
30c4440c 193parameter_index_in_region (tree name, sese_info_p region)
2abae5f1
SP
194{
195 int i;
196 tree p;
65b016eb 197 FOR_EACH_VEC_ELT (region->params, i, p)
2abae5f1
SP
198 if (p == name)
199 return i;
2abae5f1
SP
200 return -1;
201}
202
33ad93b9 203/* Extract an affine expression from the tree E in the scop S. */
2abae5f1 204
33ad93b9
RG
205static isl_pw_aff *
206extract_affine (scop_p s, tree e, __isl_take isl_space *space)
2abae5f1 207{
33ad93b9 208 isl_pw_aff *lhs, *rhs, *res;
33ad93b9
RG
209
210 if (e == chrec_dont_know) {
211 isl_space_free (space);
212 return NULL;
213 }
2abae5f1 214
f6b5c26b 215 tree type = TREE_TYPE (e);
2abae5f1
SP
216 switch (TREE_CODE (e))
217 {
218 case POLYNOMIAL_CHREC:
33ad93b9 219 res = extract_affine_chrec (s, e, space);
2abae5f1
SP
220 break;
221
222 case MULT_EXPR:
33ad93b9 223 res = extract_affine_mul (s, e, space);
2abae5f1
SP
224 break;
225
2abae5f1 226 case POINTER_PLUS_EXPR:
f6b5c26b
RB
227 {
228 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
229 /* The RHS of a pointer-plus expression is to be interpreted
230 as signed value. Try to look through a sign-changing conversion
231 first. */
232 tree tem = TREE_OPERAND (e, 1);
233 STRIP_NOPS (tem);
234 rhs = extract_affine (s, tem, space);
235 if (TYPE_UNSIGNED (TREE_TYPE (tem)))
236 rhs = wrap (rhs, TYPE_PRECISION (type) - 1);
237 res = isl_pw_aff_add (lhs, rhs);
238 break;
239 }
240
241 case PLUS_EXPR:
33ad93b9
RG
242 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
243 rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
244 res = isl_pw_aff_add (lhs, rhs);
2abae5f1
SP
245 break;
246
247 case MINUS_EXPR:
33ad93b9
RG
248 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
249 rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
250 res = isl_pw_aff_sub (lhs, rhs);
251 break;
2abae5f1 252
33ad93b9 253 case BIT_NOT_EXPR:
f6b5c26b
RB
254 lhs = extract_affine (s, integer_minus_one_node, isl_space_copy (space));
255 rhs = extract_affine (s, TREE_OPERAND (e, 0), space);
256 res = isl_pw_aff_sub (lhs, rhs);
fa8ce189
RB
257 /* We need to always wrap the result of a bitwise operation. */
258 return wrap (res, TYPE_PRECISION (type) - (TYPE_UNSIGNED (type) ? 0 : 1));
f6b5c26b
RB
259
260 case NEGATE_EXPR:
33ad93b9
RG
261 lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
262 rhs = extract_affine (s, integer_minus_one_node, space);
263 res = isl_pw_aff_mul (lhs, rhs);
264 break;
2abae5f1 265
33ad93b9 266 case SSA_NAME:
30c4440c
RB
267 {
268 gcc_assert (! defined_in_sese_p (e, s->scop_info->region));
269 int dim = parameter_index_in_region (e, s->scop_info);
270 gcc_assert (dim != -1);
fa8ce189
RB
271 /* No need to wrap a parameter. */
272 return extract_affine_name (dim, space);
30c4440c 273 }
2abae5f1 274
33ad93b9
RG
275 case INTEGER_CST:
276 res = extract_affine_int (e, space);
277 /* No need to wrap a single integer. */
278 return res;
2abae5f1 279
33ad93b9 280 CASE_CONVERT:
57cfa172
RB
281 {
282 tree itype = TREE_TYPE (TREE_OPERAND (e, 0));
283 res = extract_affine (s, TREE_OPERAND (e, 0), space);
284 /* Signed values, even if overflow is undefined, get modulo-reduced.
285 But only if not all values of the old type fit in the new. */
286 if (! TYPE_UNSIGNED (type)
fa8ce189 287 && ((TYPE_UNSIGNED (itype)
57cfa172
RB
288 && TYPE_PRECISION (type) <= TYPE_PRECISION (itype))
289 || TYPE_PRECISION (type) < TYPE_PRECISION (itype)))
290 res = wrap (res, TYPE_PRECISION (type) - 1);
fa8ce189
RB
291 else if (TYPE_UNSIGNED (type)
292 && (!TYPE_UNSIGNED (itype)
293 || TYPE_PRECISION (type) < TYPE_PRECISION (itype)))
294 res = wrap (res, TYPE_PRECISION (type));
295 return res;
57cfa172 296 }
f6b5c26b 297
33ad93b9
RG
298 case NON_LVALUE_EXPR:
299 res = extract_affine (s, TREE_OPERAND (e, 0), space);
300 break;
2abae5f1 301
33ad93b9
RG
302 default:
303 gcc_unreachable ();
304 break;
305 }
2abae5f1 306
fa8ce189
RB
307 /* For all wrapping arithmetic wrap the result. */
308 if (TYPE_OVERFLOW_WRAPS (type))
33ad93b9 309 res = wrap (res, TYPE_PRECISION (type));
2abae5f1 310
33ad93b9
RG
311 return res;
312}
2abae5f1 313
2abae5f1
SP
314/* Returns a linear expression for tree T evaluated in PBB. */
315
33ad93b9 316static isl_pw_aff *
8eedca0d 317create_pw_aff_from_tree (poly_bb_p pbb, loop_p loop, tree t)
2abae5f1 318{
33ad93b9 319 scop_p scop = PBB_SCOP (pbb);
2abae5f1 320
124f4f57 321 t = cached_scalar_evolution_in_region (scop->scop_info->region, loop, t);
36f40be0 322
adba512d 323 gcc_assert (!chrec_contains_undetermined (t));
2abae5f1
SP
324 gcc_assert (!automatically_generated_chrec_p (t));
325
33ad93b9 326 return extract_affine (scop, t, isl_set_get_space (pbb->domain));
2abae5f1
SP
327}
328
33ad93b9
RG
329/* Add conditional statement STMT to pbb. CODE is used as the comparison
330 operator. This allows us to invert the condition or to handle
331 inequalities. */
2abae5f1 332
adba512d 333static void
538dd0b7 334add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code)
2abae5f1 335{
8eedca0d
RB
336 loop_p loop = gimple_bb (stmt)->loop_father;
337 isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_lhs (stmt));
338 isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_rhs (stmt));
2abae5f1 339
36f40be0 340 isl_set *cond;
33ad93b9 341 switch (code)
2abae5f1 342 {
33ad93b9
RG
343 case LT_EXPR:
344 cond = isl_pw_aff_lt_set (lhs, rhs);
345 break;
2abae5f1 346
33ad93b9
RG
347 case GT_EXPR:
348 cond = isl_pw_aff_gt_set (lhs, rhs);
349 break;
2abae5f1 350
33ad93b9
RG
351 case LE_EXPR:
352 cond = isl_pw_aff_le_set (lhs, rhs);
353 break;
2abae5f1 354
33ad93b9
RG
355 case GE_EXPR:
356 cond = isl_pw_aff_ge_set (lhs, rhs);
357 break;
2abae5f1 358
33ad93b9
RG
359 case EQ_EXPR:
360 cond = isl_pw_aff_eq_set (lhs, rhs);
361 break;
2abae5f1 362
33ad93b9
RG
363 case NE_EXPR:
364 cond = isl_pw_aff_ne_set (lhs, rhs);
365 break;
2abae5f1 366
33ad93b9 367 default:
adba512d 368 gcc_unreachable ();
2abae5f1 369 }
33ad93b9
RG
370
371 cond = isl_set_coalesce (cond);
372 cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain));
14b1747c 373 pbb->domain = isl_set_coalesce (isl_set_intersect (pbb->domain, cond));
2abae5f1
SP
374}
375
376/* Add conditions to the domain of PBB. */
377
adba512d 378static void
2abae5f1
SP
379add_conditions_to_domain (poly_bb_p pbb)
380{
381 unsigned int i;
355fe088 382 gimple *stmt;
65ef70d6 383 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
2abae5f1 384
9771b263 385 if (GBB_CONDITIONS (gbb).is_empty ())
adba512d 386 return;
2abae5f1 387
9771b263 388 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
2abae5f1
SP
389 switch (gimple_code (stmt))
390 {
391 case GIMPLE_COND:
392 {
4bc4dd11
AK
393 /* Don't constrain on anything else than INTEGER_TYPE. */
394 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt))) != INTEGER_TYPE)
395 break;
396
538dd0b7
DM
397 gcond *cond_stmt = as_a <gcond *> (stmt);
398 enum tree_code code = gimple_cond_code (cond_stmt);
2abae5f1
SP
399
400 /* The conditions for ELSE-branches are inverted. */
9771b263 401 if (!GBB_CONDITION_CASES (gbb)[i])
2abae5f1
SP
402 code = invert_tree_comparison (code, false);
403
adba512d 404 add_condition_to_pbb (pbb, cond_stmt, code);
2abae5f1
SP
405 break;
406 }
407
2abae5f1
SP
408 default:
409 gcc_unreachable ();
410 break;
411 }
efa21390
SP
412}
413
2abae5f1
SP
414/* Add constraints on the possible values of parameter P from the type
415 of P. */
416
417static void
30c4440c 418add_param_constraints (scop_p scop, graphite_dim_t p, tree parameter)
2abae5f1 419{
2abae5f1 420 tree type = TREE_TYPE (parameter);
45f4e2b0 421 value_range r;
30c4440c 422 wide_int min, max;
2abae5f1 423
30c4440c 424 gcc_assert (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type));
697f511d 425
30c4440c 426 if (INTEGRAL_TYPE_P (type)
45f4e2b0
AH
427 && get_range_query (cfun)->range_of_expr (r, parameter)
428 && !r.undefined_p ())
429 {
430 min = r.lower_bound ();
431 max = r.upper_bound ();
432 }
697f511d 433 else
2abae5f1 434 {
30c4440c
RB
435 min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
436 max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
2abae5f1
SP
437 }
438
30c4440c
RB
439 isl_space *space = isl_set_get_space (scop->param_context);
440 isl_constraint *c = isl_inequality_alloc (isl_local_space_from_space (space));
441 isl_val *v = isl_val_int_from_wi (scop->isl_context,
442 widest_int::from (min, TYPE_SIGN (type)));
443 v = isl_val_neg (v);
444 c = isl_constraint_set_constant_val (c, v);
445 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, 1);
446 scop->param_context = isl_set_coalesce
447 (isl_set_add_constraint (scop->param_context, c));
448
449 space = isl_set_get_space (scop->param_context);
450 c = isl_inequality_alloc (isl_local_space_from_space (space));
451 v = isl_val_int_from_wi (scop->isl_context,
452 widest_int::from (max, TYPE_SIGN (type)));
453 c = isl_constraint_set_constant_val (c, v);
454 c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, -1);
455 scop->param_context = isl_set_coalesce
456 (isl_set_add_constraint (scop->param_context, c));
2abae5f1
SP
457}
458
2abae5f1
SP
459/* Add a constrain to the ACCESSES polyhedron for the alias set of
460 data reference DR. ACCESSP_NB_DIMS is the dimension of the
461 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
462 domain. */
463
33ad93b9 464static isl_map *
09fefdad 465pdr_add_alias_set (isl_map *acc, dr_info &dri)
2abae5f1 466{
790befae 467 isl_constraint *c = isl_equality_alloc
33ad93b9 468 (isl_local_space_from_space (isl_map_get_space (acc)));
65b016eb 469 /* Positive numbers for all alias sets. */
09fefdad 470 c = isl_constraint_set_constant_si (c, -dri.alias_set);
33ad93b9
RG
471 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
472
473 return isl_map_add_constraint (acc, c);
474}
475
476/* Assign the affine expression INDEX to the output dimension POS of
477 MAP and return the result. */
478
479static isl_map *
480set_index (isl_map *map, int pos, isl_pw_aff *index)
481{
482 isl_map *index_map;
483 int len = isl_map_dim (map, isl_dim_out);
484 isl_id *id;
485
486 index_map = isl_map_from_pw_aff (index);
487 index_map = isl_map_insert_dims (index_map, isl_dim_out, 0, pos);
488 index_map = isl_map_add_dims (index_map, isl_dim_out, len - pos - 1);
2abae5f1 489
33ad93b9
RG
490 id = isl_map_get_tuple_id (map, isl_dim_out);
491 index_map = isl_map_set_tuple_id (index_map, isl_dim_out, id);
492 id = isl_map_get_tuple_id (map, isl_dim_in);
493 index_map = isl_map_set_tuple_id (index_map, isl_dim_in, id);
2abae5f1 494
33ad93b9 495 return isl_map_intersect (map, index_map);
2abae5f1
SP
496}
497
498/* Add to ACCESSES polyhedron equalities defining the access functions
499 to the memory. ACCESSP_NB_DIMS is the dimension of the ACCESSES
500 polyhedron, DOM_NB_DIMS is the dimension of the iteration domain.
501 PBB is the poly_bb_p that contains the data reference DR. */
502
33ad93b9 503static isl_map *
09fefdad 504pdr_add_memory_accesses (isl_map *acc, dr_info &dri)
2abae5f1 505{
09fefdad
AK
506 data_reference_p dr = dri.dr;
507 poly_bb_p pbb = dri.pbb;
2abae5f1 508 int i, nb_subscripts = DR_NUM_DIMENSIONS (dr);
2abae5f1 509 scop_p scop = PBB_SCOP (pbb);
2abae5f1
SP
510
511 for (i = 0; i < nb_subscripts; i++)
512 {
33ad93b9 513 isl_pw_aff *aff;
ce6a2c92 514 tree afn = DR_ACCESS_FN (dr, i);
2abae5f1 515
33ad93b9
RG
516 aff = extract_affine (scop, afn,
517 isl_space_domain (isl_map_get_space (acc)));
09bf990e 518 acc = set_index (acc, nb_subscripts - i , aff);
2abae5f1
SP
519 }
520
14b1747c 521 return isl_map_coalesce (acc);
2abae5f1
SP
522}
523
2e733703
AK
524/* Return true when the LOW and HIGH bounds of an array reference REF are valid
525 to extract constraints on accessed elements of the array. Returning false is
526 the conservative answer. */
527
528static bool
529bounds_are_valid (tree ref, tree low, tree high)
530{
531 if (!high)
532 return false;
533
534 if (!tree_fits_shwi_p (low)
535 || !tree_fits_shwi_p (high))
536 return false;
537
538 /* 1-element arrays at end of structures may extend over
539 their declared size. */
540 if (array_at_struct_end_p (ref)
541 && operand_equal_p (low, high, 0))
542 return false;
543
544 /* Fortran has some arrays where high bound is -1 and low is 0. */
545 if (integer_onep (fold_build2 (LT_EXPR, boolean_type_node, high, low)))
546 return false;
547
548 return true;
549}
550
2abae5f1 551/* Add constrains representing the size of the accessed data to the
66096911
SP
552 ACCESSES polyhedron. ACCESSP_NB_DIMS is the dimension of the
553 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
2abae5f1
SP
554 domain. */
555
33ad93b9 556static isl_set *
24757752
AK
557pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop,
558 data_reference_p dr)
2abae5f1
SP
559{
560 tree ref = DR_REF (dr);
2abae5f1 561
24757752
AK
562 int nb_subscripts = DR_NUM_DIMENSIONS (dr);
563 for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0))
2abae5f1 564 {
98f3eb1f 565 if (TREE_CODE (ref) != ARRAY_REF)
24757752 566 return subscript_sizes;
2abae5f1 567
24757752
AK
568 tree low = array_ref_low_bound (ref);
569 tree high = array_ref_up_bound (ref);
98f3eb1f 570
2e733703
AK
571 if (!bounds_are_valid (ref, low, high))
572 continue;
573
574 isl_space *space = isl_set_get_space (subscript_sizes);
575 isl_pw_aff *lb = extract_affine_int (low, isl_space_copy (space));
576 isl_pw_aff *ub = extract_affine_int (high, isl_space_copy (space));
577
578 /* high >= 0 */
579 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub));
580 valid = isl_set_project_out (valid, isl_dim_set, 0,
581 isl_set_dim (valid, isl_dim_set));
14b1747c
AK
582 scop->param_context = isl_set_coalesce
583 (isl_set_intersect (scop->param_context, valid));
2e733703
AK
584
585 isl_aff *aff
586 = isl_aff_zero_on_domain (isl_local_space_from_space (space));
587 aff = isl_aff_add_coefficient_si (aff, isl_dim_in, i + 1, 1);
588 isl_set *univ
589 = isl_set_universe (isl_space_domain (isl_aff_get_space (aff)));
590 isl_pw_aff *index = isl_pw_aff_alloc (univ, aff);
591
592 isl_id *id = isl_set_get_tuple_id (subscript_sizes);
593 lb = isl_pw_aff_set_tuple_id (lb, isl_dim_in, isl_id_copy (id));
594 ub = isl_pw_aff_set_tuple_id (ub, isl_dim_in, id);
595
596 /* low <= sub_i <= high */
597 isl_set *lbs = isl_pw_aff_ge_set (isl_pw_aff_copy (index), lb);
598 isl_set *ubs = isl_pw_aff_le_set (index, ub);
599 subscript_sizes = isl_set_intersect (subscript_sizes, lbs);
600 subscript_sizes = isl_set_intersect (subscript_sizes, ubs);
2abae5f1 601 }
33ad93b9 602
14b1747c 603 return isl_set_coalesce (subscript_sizes);
2abae5f1
SP
604}
605
65b016eb 606/* Build data accesses for DRI. */
2abae5f1
SP
607
608static void
09fefdad 609build_poly_dr (dr_info &dri)
2abae5f1 610{
33ad93b9 611 isl_map *acc;
24757752 612 isl_set *subscript_sizes;
09fefdad
AK
613 poly_bb_p pbb = dri.pbb;
614 data_reference_p dr = dri.dr;
33ad93b9 615 scop_p scop = PBB_SCOP (pbb);
65b016eb 616 isl_id *id = isl_id_for_dr (scop);
2abae5f1 617
33ad93b9
RG
618 {
619 isl_space *dc = isl_set_get_space (pbb->domain);
620 int nb_out = 1 + DR_NUM_DIMENSIONS (dr);
621 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
622 isl_dim_out, nb_out);
2abae5f1 623
33ad93b9 624 acc = isl_map_universe (space);
65b016eb 625 acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id));
33ad93b9 626 }
2abae5f1 627
09fefdad
AK
628 acc = pdr_add_alias_set (acc, dri);
629 acc = pdr_add_memory_accesses (acc, dri);
2abae5f1 630
33ad93b9 631 {
33ad93b9 632 int nb = 1 + DR_NUM_DIMENSIONS (dr);
8e4dc590 633 isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb);
33ad93b9
RG
634
635 space = isl_space_set_tuple_id (space, isl_dim_set, id);
24757752
AK
636 subscript_sizes = isl_set_nat_universe (space);
637 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
09fefdad 638 dri.alias_set);
24757752 639 subscript_sizes = pdr_add_data_dimensions (subscript_sizes, scop, dr);
33ad93b9 640 }
2abae5f1 641
65b016eb
AK
642 new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE,
643 acc, subscript_sizes);
2abae5f1
SP
644}
645
278b1a1d 646static void
65b016eb
AK
647build_poly_sr_1 (poly_bb_p pbb, gimple *stmt, tree var, enum poly_dr_type kind,
648 isl_map *acc, isl_set *subscript_sizes)
278b1a1d 649{
99124c31 650 scop_p scop = PBB_SCOP (pbb);
65b016eb 651 /* Each scalar variables has a unique alias set number starting from
99124c31
RB
652 the maximum alias set assigned to a dr. */
653 int alias_set = scop->max_alias_set + SSA_NAME_VERSION (var);
65b016eb 654 subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
99124c31
RB
655 alias_set);
656
657 /* Add a constrain to the ACCESSES polyhedron for the alias set of
658 data reference DR. */
659 isl_constraint *c
660 = isl_equality_alloc (isl_local_space_from_space (isl_map_get_space (acc)));
661 c = isl_constraint_set_constant_si (c, -alias_set);
662 c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
65b016eb 663
99124c31 664 new_poly_dr (pbb, stmt, kind, isl_map_add_constraint (acc, c),
65b016eb 665 subscript_sizes);
278b1a1d
SP
666}
667
65b016eb 668/* Record all cross basic block scalar variables in PBB. */
2abae5f1
SP
669
670static void
65b016eb 671build_poly_sr (poly_bb_p pbb)
2abae5f1 672{
65b016eb 673 scop_p scop = PBB_SCOP (pbb);
65ef70d6 674 gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
0ddb9c8d
AK
675 vec<scalar_use> &reads = gbb->read_scalar_refs;
676 vec<tree> &writes = gbb->write_scalar_refs;
1c2a7491 677
65b016eb
AK
678 isl_space *dc = isl_set_get_space (pbb->domain);
679 int nb_out = 1;
680 isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
681 isl_dim_out, nb_out);
682 isl_id *id = isl_id_for_dr (scop);
683 space = isl_space_set_tuple_id (space, isl_dim_set, isl_id_copy (id));
684 isl_map *acc = isl_map_universe (isl_space_copy (space));
685 acc = isl_map_set_tuple_id (acc, isl_dim_out, id);
686 isl_set *subscript_sizes = isl_set_nat_universe (space);
9773d730 687
caf5b4df 688 int i;
65b016eb
AK
689 tree var;
690 FOR_EACH_VEC_ELT (writes, i, var)
691 build_poly_sr_1 (pbb, SSA_NAME_DEF_STMT (var), var, PDR_WRITE,
692 isl_map_copy (acc), isl_set_copy (subscript_sizes));
5d737345 693
65b016eb
AK
694 scalar_use *use;
695 FOR_EACH_VEC_ELT (reads, i, use)
696 build_poly_sr_1 (pbb, use->first, use->second, PDR_READ, isl_map_copy (acc),
697 isl_set_copy (subscript_sizes));
d5b5a232 698
65b016eb
AK
699 isl_map_free (acc);
700 isl_set_free (subscript_sizes);
5dcc64d9
SP
701}
702
65b016eb 703/* Build data references in SCOP. */
ee646fc6 704
efa21390 705static void
65b016eb 706build_scop_drs (scop_p scop)
ee646fc6 707{
caf5b4df 708 int i;
65b016eb
AK
709 dr_info *dri;
710 FOR_EACH_VEC_ELT (scop->drs, i, dri)
711 build_poly_dr (*dri);
5dcc64d9 712
65b016eb
AK
713 poly_bb_p pbb;
714 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
715 build_poly_sr (pbb);
2abae5f1
SP
716}
717
adba512d
AK
718/* Add to the iteration DOMAIN one extra dimension for LOOP->num. */
719
720static isl_set *
721add_iter_domain_dimension (__isl_take isl_set *domain, loop_p loop, scop_p scop)
722{
723 int loop_index = isl_set_dim (domain, isl_dim_set);
724 domain = isl_set_add_dims (domain, isl_dim_set, 1);
725 char name[50];
726 snprintf (name, sizeof(name), "i%d", loop->num);
727 isl_id *label = isl_id_alloc (scop->isl_context, name, NULL);
728 return isl_set_set_dim_id (domain, isl_dim_set, loop_index, label);
729}
730
d8d262cf
AK
731/* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */
732
733static isl_set *
734add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop,
735 loop_p context)
736{
737 if (loop == context)
738 return domain;
739 const sese_l &region = scop->scop_info->region;
740 if (!loop_in_sese_p (loop, region))
a68f286c
RB
741 return domain;
742
743 /* Recursion all the way up to the context loop. */
744 domain = add_loop_constraints (scop, domain, loop_outer (loop), context);
d8d262cf
AK
745
746 /* Then, build constraints over the loop in post-order: outer to inner. */
747
748 int loop_index = isl_set_dim (domain, isl_dim_set);
749 if (dump_file)
750 fprintf (dump_file, "[sese-to-poly] adding one extra dimension to the "
751 "domain for loop_%d.\n", loop->num);
adba512d 752 domain = add_iter_domain_dimension (domain, loop, scop);
d8d262cf
AK
753 isl_space *space = isl_set_get_space (domain);
754
755 /* 0 <= loop_i */
756 isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
757 isl_constraint *c = isl_inequality_alloc (ls);
758 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, 1);
759 if (dump_file)
760 {
761 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
762 print_isl_constraint (dump_file, c);
763 }
764 domain = isl_set_add_constraint (domain, c);
765
766 tree nb_iters = number_of_latch_executions (loop);
767 if (TREE_CODE (nb_iters) == INTEGER_CST)
768 {
769 /* loop_i <= cst_nb_iters */
770 isl_local_space *ls = isl_local_space_from_space (space);
771 isl_constraint *c = isl_inequality_alloc (ls);
772 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
cc46a51d
RB
773 isl_val *v
774 = isl_val_int_from_wi (scop->isl_context, wi::to_widest (nb_iters));
d8d262cf
AK
775 c = isl_constraint_set_constant_val (c, v);
776 return isl_set_add_constraint (domain, c);
777 }
778 /* loop_i <= expr_nb_iters */
779 gcc_assert (!chrec_contains_undetermined (nb_iters));
124f4f57 780 nb_iters = cached_scalar_evolution_in_region (region, loop, nb_iters);
d8d262cf
AK
781 gcc_assert (!chrec_contains_undetermined (nb_iters));
782
783 isl_pw_aff *aff_nb_iters = extract_affine (scop, nb_iters,
784 isl_space_copy (space));
785 isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters));
786 valid = isl_set_project_out (valid, isl_dim_set, 0,
787 isl_set_dim (valid, isl_dim_set));
788
789 if (valid)
790 scop->param_context = isl_set_intersect (scop->param_context, valid);
791
792 ls = isl_local_space_from_space (isl_space_copy (space));
793 isl_aff *loop_i = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls),
794 isl_dim_in, loop_index, 1);
795 isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i),
796 isl_pw_aff_copy (aff_nb_iters));
797 if (dump_file)
798 {
799 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
800 print_isl_set (dump_file, le);
801 }
802 domain = isl_set_intersect (domain, le);
803
804 widest_int nit;
805 if (!max_stmt_executions (loop, &nit))
806 {
807 isl_pw_aff_free (aff_nb_iters);
808 isl_space_free (space);
809 return domain;
810 }
811
812 /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we
813 do not know whether the loop executes at least once. */
cc46a51d 814 --nit;
d8d262cf 815
cc46a51d 816 isl_pw_aff *approx = extract_affine_wi (nit, isl_space_copy (space));
d8d262cf
AK
817 isl_set *x = isl_pw_aff_ge_set (approx, aff_nb_iters);
818 x = isl_set_project_out (x, isl_dim_set, 0,
819 isl_set_dim (x, isl_dim_set));
820 scop->param_context = isl_set_intersect (scop->param_context, x);
821
822 ls = isl_local_space_from_space (space);
823 c = isl_inequality_alloc (ls);
824 c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
cc46a51d 825 isl_val *v = isl_val_int_from_wi (scop->isl_context, nit);
d8d262cf
AK
826 c = isl_constraint_set_constant_val (c, v);
827
828 if (dump_file)
829 {
830 fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
831 print_isl_constraint (dump_file, c);
832 }
833
834 return isl_set_add_constraint (domain, c);
835}
836
837/* Builds the original iteration domains for each pbb in the SCOP. */
838
839static int
adba512d
AK
840build_iteration_domains (scop_p scop, __isl_keep isl_set *context,
841 int index, loop_p context_loop)
d8d262cf
AK
842{
843 loop_p current = pbb_loop (scop->pbbs[index]);
844 isl_set *domain = isl_set_copy (context);
845 domain = add_loop_constraints (scop, domain, current, context_loop);
846 const sese_l &region = scop->scop_info->region;
847
848 int i;
849 poly_bb_p pbb;
850 FOR_EACH_VEC_ELT_FROM (scop->pbbs, i, pbb, index)
851 {
852 loop_p loop = pbb_loop (pbb);
853 if (current == loop)
854 {
adba512d 855 pbb->iterators = isl_set_copy (domain);
d8d262cf
AK
856 pbb->domain = isl_set_copy (domain);
857 pbb->domain = isl_set_set_tuple_id (pbb->domain,
858 isl_id_for_pbb (scop, pbb));
adba512d
AK
859 add_conditions_to_domain (pbb);
860
d8d262cf
AK
861 if (dump_file)
862 {
863 fprintf (dump_file, "[sese-to-poly] set pbb_%d->domain: ",
864 pbb_index (pbb));
865 print_isl_set (dump_file, domain);
866 }
867 continue;
868 }
869
870 while (loop_in_sese_p (loop, region)
871 && current != loop)
872 loop = loop_outer (loop);
873
874 if (current != loop)
875 {
876 /* A statement in a different loop nest than CURRENT loop. */
877 isl_set_free (domain);
878 return i;
879 }
880
881 /* A statement nested in the CURRENT loop. */
882 i = build_iteration_domains (scop, domain, i, current);
883 i--;
884 }
885
886 isl_set_free (domain);
887 return i;
888}
889
d8d262cf
AK
890/* Assign dimension for each parameter in SCOP and add constraints for the
891 parameters. */
892
893static void
894build_scop_context (scop_p scop)
895{
896 sese_info_p region = scop->scop_info;
897 unsigned nbp = sese_nb_params (region);
898 isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0);
899
900 unsigned i;
901 tree e;
902 FOR_EACH_VEC_ELT (region->params, i, e)
903 space = isl_space_set_dim_id (space, isl_dim_param, i,
904 isl_id_for_ssa_name (scop, e));
905
906 scop->param_context = isl_set_universe (space);
907
30c4440c
RB
908 FOR_EACH_VEC_ELT (region->params, i, e)
909 add_param_constraints (scop, i, e);
d8d262cf
AK
910}
911
adba512d
AK
912/* Return true when loop A is nested in loop B. */
913
914static bool
915nested_in (loop_p a, loop_p b)
916{
917 return b == find_common_loop (a, b);
918}
919
920/* Return the loop at a specific SCOP->pbbs[*INDEX]. */
921static loop_p
922loop_at (scop_p scop, int *index)
923{
924 return pbb_loop (scop->pbbs[*index]);
925}
926
927/* Return the index of any pbb belonging to loop or a subloop of A. */
928
929static int
930index_outermost_in_loop (loop_p a, scop_p scop)
931{
932 int i, outermost = -1;
933 int last_depth = -1;
934 poly_bb_p pbb;
935 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
936 if (nested_in (pbb_loop (pbb), a)
937 && (last_depth == -1
938 || last_depth > (int) loop_depth (pbb_loop (pbb))))
939 {
940 outermost = i;
941 last_depth = loop_depth (pbb_loop (pbb));
942 }
943 return outermost;
944}
945
946/* Return the index of any pbb belonging to loop or a subloop of A. */
947
948static int
949index_pbb_in_loop (loop_p a, scop_p scop)
950{
951 int i;
952 poly_bb_p pbb;
953 FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
954 if (pbb_loop (pbb) == a)
955 return i;
956 return -1;
957}
958
959static poly_bb_p
960outermost_pbb_in (loop_p loop, scop_p scop)
961{
962 int x = index_pbb_in_loop (loop, scop);
963 if (x == -1)
964 x = index_outermost_in_loop (loop, scop);
965 return scop->pbbs[x];
966}
967
968static isl_schedule *
969add_in_sequence (__isl_take isl_schedule *a, __isl_take isl_schedule *b)
970{
971 gcc_assert (a || b);
972
973 if (!a)
974 return b;
975
976 if (!b)
977 return a;
978
979 return isl_schedule_sequence (a, b);
980}
981
982struct map_to_dimension_data {
983 int n;
984 isl_union_pw_multi_aff *res;
985};
986
987/* Create a function that maps the elements of SET to its N-th dimension and add
988 it to USER->res. */
989
990static isl_stat
991add_outer_projection (__isl_take isl_set *set, void *user)
992{
993 struct map_to_dimension_data *data = (struct map_to_dimension_data *) user;
994 int dim = isl_set_dim (set, isl_dim_set);
995 isl_space *space = isl_set_get_space (set);
996
997 gcc_assert (dim >= data->n);
998 isl_pw_multi_aff *pma
999 = isl_pw_multi_aff_project_out_map (space, isl_dim_set, data->n,
1000 dim - data->n);
1001 data->res = isl_union_pw_multi_aff_add_pw_multi_aff (data->res, pma);
1002
1003 isl_set_free (set);
1004 return isl_stat_ok;
1005}
1006
1007/* Return SET in which all inner dimensions above N are removed. */
1008
1009static isl_multi_union_pw_aff *
1010outer_projection_mupa (__isl_take isl_union_set *set, int n)
1011{
1012 gcc_assert (n >= 0);
1013 gcc_assert (set);
1014 gcc_assert (!isl_union_set_is_empty (set));
1015
1016 isl_space *space = isl_union_set_get_space (set);
1017 isl_union_pw_multi_aff *pwaff = isl_union_pw_multi_aff_empty (space);
1018
1019 struct map_to_dimension_data data = {n, pwaff};
1020
1021 if (isl_union_set_foreach_set (set, &add_outer_projection, &data) < 0)
1022 data.res = isl_union_pw_multi_aff_free (data.res);
1023
1024 isl_union_set_free (set);
1025 return isl_multi_union_pw_aff_from_union_pw_multi_aff (data.res);
1026}
1027
1028/* Embed SCHEDULE in the constraints of the LOOP domain. */
1029
1030static isl_schedule *
1031add_loop_schedule (__isl_take isl_schedule *schedule, loop_p loop,
1032 scop_p scop)
1033{
1034 poly_bb_p pbb = outermost_pbb_in (loop, scop);
1035 isl_set *iterators = pbb->iterators;
1036
1037 int empty = isl_set_is_empty (iterators);
1038 if (empty < 0 || empty)
1039 return empty < 0 ? isl_schedule_free (schedule) : schedule;
1040
197d2f5b 1041 isl_union_set *domain = isl_schedule_get_domain (schedule);
f0c216e1 1042 /* We cannot apply an empty domain to pbbs in this loop so return early. */
197d2f5b
RB
1043 if (isl_union_set_is_empty (domain))
1044 {
197d2f5b
RB
1045 isl_union_set_free (domain);
1046 return schedule;
1047 }
1048
adba512d
AK
1049 isl_space *space = isl_set_get_space (iterators);
1050 int loop_index = isl_space_dim (space, isl_dim_set) - 1;
1051
1052 loop_p ploop = pbb_loop (pbb);
1053 while (loop != ploop)
1054 {
1055 --loop_index;
1056 ploop = loop_outer (ploop);
1057 }
1058
1059 isl_local_space *ls = isl_local_space_from_space (space);
1060 isl_aff *aff = isl_aff_var_on_domain (ls, isl_dim_set, loop_index);
1061 isl_multi_aff *prefix = isl_multi_aff_from_aff (aff);
1062 char name[50];
1063 snprintf (name, sizeof(name), "L_%d", loop->num);
1064 isl_id *label = isl_id_alloc (isl_schedule_get_ctx (schedule),
1065 name, NULL);
1066 prefix = isl_multi_aff_set_tuple_id (prefix, isl_dim_out, label);
1067
1068 int n = isl_multi_aff_dim (prefix, isl_dim_in);
adba512d
AK
1069 isl_multi_union_pw_aff *mupa = outer_projection_mupa (domain, n);
1070 mupa = isl_multi_union_pw_aff_apply_multi_aff (mupa, prefix);
1071 return isl_schedule_insert_partial_schedule (schedule, mupa);
1072}
1073
1074/* Build schedule for the pbb at INDEX. */
1075
1076static isl_schedule *
1077build_schedule_pbb (scop_p scop, int *index)
1078{
1079 poly_bb_p pbb = scop->pbbs[*index];
1080 ++*index;
1081 isl_set *domain = isl_set_copy (pbb->domain);
1082 isl_union_set *ud = isl_union_set_from_set (domain);
1083 return isl_schedule_from_domain (ud);
1084}
1085
1086static isl_schedule *build_schedule_loop_nest (scop_p, int *, loop_p);
1087
1088/* Build the schedule of the loop containing the SCOP pbb at INDEX. */
1089
1090static isl_schedule *
1091build_schedule_loop (scop_p scop, int *index)
1092{
1093 int max = scop->pbbs.length ();
1094 gcc_assert (*index < max);
1095 loop_p loop = loop_at (scop, index);
1096
1097 isl_schedule *s = NULL;
1098 while (nested_in (loop_at (scop, index), loop))
1099 {
1100 if (loop == loop_at (scop, index))
1101 s = add_in_sequence (s, build_schedule_pbb (scop, index));
1102 else
1103 s = add_in_sequence (s, build_schedule_loop_nest (scop, index, loop));
1104
1105 if (*index == max)
1106 break;
1107 }
1108
1109 return add_loop_schedule (s, loop, scop);
1110}
1111
1112/* S is the schedule of the loop LOOP. Embed the schedule S in all outer loops.
1113 When CONTEXT_LOOP is null, embed the schedule in all loops contained in the
1114 SCOP surrounding LOOP. When CONTEXT_LOOP is non null, only embed S in the
1115 maximal loop nest contained within CONTEXT_LOOP. */
1116
1117static isl_schedule *
1118embed_in_surrounding_loops (__isl_take isl_schedule *s, scop_p scop,
1119 loop_p loop, int *index, loop_p context_loop)
1120{
1121 loop_p outer = loop_outer (loop);
1122 sese_l region = scop->scop_info->region;
1123 if (context_loop == outer
1124 || !loop_in_sese_p (outer, region))
1125 return s;
1126
1127 int max = scop->pbbs.length ();
1128 if (*index == max
1129 || (context_loop && !nested_in (loop_at (scop, index), context_loop))
1130 || (!context_loop
1131 && !loop_in_sese_p (find_common_loop (outer, loop_at (scop, index)),
1132 region)))
1133 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop),
1134 scop, outer, index, context_loop);
1135
1136 bool a_pbb;
1137 while ((a_pbb = (outer == loop_at (scop, index)))
1138 || nested_in (loop_at (scop, index), outer))
1139 {
1140 if (a_pbb)
1141 s = add_in_sequence (s, build_schedule_pbb (scop, index));
1142 else
1143 s = add_in_sequence (s, build_schedule_loop (scop, index));
1144
1145 if (*index == max)
1146 break;
1147 }
1148
1149 /* We reached the end of the OUTER loop: embed S in OUTER. */
1150 return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), scop,
1151 outer, index, context_loop);
1152}
1153
1154/* Build schedule for the full loop nest containing the pbb at INDEX. When
1155 CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP
1156 surrounding the pbb. When CONTEXT_LOOP is non null, only build the maximal loop
1157 nest contained within CONTEXT_LOOP. */
1158
1159static isl_schedule *
1160build_schedule_loop_nest (scop_p scop, int *index, loop_p context_loop)
1161{
1162 gcc_assert (*index != (int) scop->pbbs.length ());
1163
1164 loop_p loop = loop_at (scop, index);
1165 isl_schedule *s = build_schedule_loop (scop, index);
1166 return embed_in_surrounding_loops (s, scop, loop, index, context_loop);
1167}
1168
1169/* Build the schedule of the SCOP. */
1170
1a8821c5 1171static void
adba512d
AK
1172build_original_schedule (scop_p scop)
1173{
1174 int i = 0;
1175 int n = scop->pbbs.length ();
1176 while (i < n)
1177 {
1178 poly_bb_p pbb = scop->pbbs[i];
1179 isl_schedule *s = NULL;
1180 if (!loop_in_sese_p (pbb_loop (pbb), scop->scop_info->region))
1181 s = build_schedule_pbb (scop, &i);
1182 else
1183 s = build_schedule_loop_nest (scop, &i, NULL);
1184
1185 scop->original_schedule = add_in_sequence (scop->original_schedule, s);
1186 }
1187
1188 if (dump_file)
1189 {
1190 fprintf (dump_file, "[sese-to-poly] original schedule:\n");
1191 print_isl_schedule (dump_file, scop->original_schedule);
1192 }
adba512d
AK
1193}
1194
2abae5f1
SP
1195/* Builds the polyhedral representation for a SESE region. */
1196
36f40be0 1197bool
2abae5f1
SP
1198build_poly_scop (scop_p scop)
1199{
871a0725
RB
1200 int old_err = isl_options_get_on_error (scop->isl_context);
1201 isl_options_set_on_error (scop->isl_context, ISL_ON_ERROR_CONTINUE);
1202
2abae5f1 1203 build_scop_context (scop);
36f40be0 1204
d8d262cf
AK
1205 unsigned i = 0;
1206 unsigned n = scop->pbbs.length ();
1207 while (i < n)
1208 i = build_iteration_domains (scop, scop->param_context, i, NULL);
1209
efa21390 1210 build_scop_drs (scop);
adba512d 1211 build_original_schedule (scop);
871a0725
RB
1212
1213 enum isl_error err = isl_ctx_last_error (scop->isl_context);
1214 isl_ctx_reset_error (scop->isl_context);
1215 isl_options_set_on_error (scop->isl_context, old_err);
ef190c93
DM
1216 if (err != isl_error_none
1217 && dump_enabled_p ())
871a0725
RB
1218 dump_printf (MSG_MISSED_OPTIMIZATION,
1219 "ISL error while building poly scop\n");
1220
1221 return err == isl_error_none;
2abae5f1 1222}
9c358739 1223#endif /* HAVE_isl */