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