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