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