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