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