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