xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/graphite-sese-to-poly.c (revision cef8759bd76c1b621f8eab8faa6f208faabc2e15)
1 /* Conversion of SESE regions to Polyhedra.
2    Copyright (C) 2009-2017 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 /* Assigns to RES the value of the INTEGER_CST T.  */
62 
63 static inline void
64 tree_int_to_gmp (tree t, mpz_t res)
65 {
66   wi::to_mpz (t, res, TYPE_SIGN (TREE_TYPE (t)));
67 }
68 
69 /* Return an isl identifier for the polyhedral basic block PBB.  */
70 
71 static isl_id *
72 isl_id_for_pbb (scop_p s, poly_bb_p pbb)
73 {
74   char name[14];
75   snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
76   return isl_id_alloc (s->isl_context, name, pbb);
77 }
78 
79 static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space);
80 
81 /* Extract an affine expression from the chain of recurrence E.  */
82 
83 static isl_pw_aff *
84 extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space)
85 {
86   isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space));
87   isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space));
88   isl_local_space *ls = isl_local_space_from_space (space);
89   unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)) - 1;
90   isl_aff *loop = isl_aff_set_coefficient_si
91     (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1);
92   isl_pw_aff *l = isl_pw_aff_from_aff (loop);
93 
94   /* Before multiplying, make sure that the result is affine.  */
95   gcc_assert (isl_pw_aff_is_cst (rhs)
96 	      || isl_pw_aff_is_cst (l));
97 
98   return isl_pw_aff_add (lhs, isl_pw_aff_mul (rhs, l));
99 }
100 
101 /* Extract an affine expression from the mult_expr E.  */
102 
103 static isl_pw_aff *
104 extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space)
105 {
106   isl_pw_aff *lhs = extract_affine (s, TREE_OPERAND (e, 0),
107 				    isl_space_copy (space));
108   isl_pw_aff *rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
109 
110   if (!isl_pw_aff_is_cst (lhs)
111       && !isl_pw_aff_is_cst (rhs))
112     {
113       isl_pw_aff_free (lhs);
114       isl_pw_aff_free (rhs);
115       return NULL;
116     }
117 
118   return isl_pw_aff_mul (lhs, rhs);
119 }
120 
121 /* Return an isl identifier from the name of the ssa_name E.  */
122 
123 static isl_id *
124 isl_id_for_ssa_name (scop_p s, tree e)
125 {
126   char name1[14];
127   snprintf (name1, sizeof (name1), "P_%d", SSA_NAME_VERSION (e));
128   return isl_id_alloc (s->isl_context, name1, e);
129 }
130 
131 /* Return an isl identifier for the data reference DR.  Data references and
132    scalar references get the same isl_id.  They need to be comparable and are
133    distinguished through the first dimension, which contains the alias set or
134    SSA_NAME_VERSION number.  */
135 
136 static isl_id *
137 isl_id_for_dr (scop_p s)
138 {
139   return isl_id_alloc (s->isl_context, "", 0);
140 }
141 
142 /* Extract an affine expression from the ssa_name E.  */
143 
144 static isl_pw_aff *
145 extract_affine_name (scop_p s, tree e, __isl_take isl_space *space)
146 {
147   isl_id *id = isl_id_for_ssa_name (s, e);
148   int dimension = isl_space_find_dim_by_id (space, isl_dim_param, id);
149   isl_id_free (id);
150   isl_set *dom = isl_set_universe (isl_space_copy (space));
151   isl_aff *aff = isl_aff_zero_on_domain (isl_local_space_from_space (space));
152   aff = isl_aff_add_coefficient_si (aff, isl_dim_param, dimension, 1);
153   return isl_pw_aff_alloc (dom, aff);
154 }
155 
156 /* Convert WI to a isl_val with CTX.  */
157 
158 static __isl_give isl_val *
159 isl_val_int_from_wi (isl_ctx *ctx, const widest_int &wi)
160 {
161   if (wi::neg_p (wi, SIGNED))
162     {
163       widest_int mwi = -wi;
164       return isl_val_neg (isl_val_int_from_chunks (ctx, mwi.get_len (),
165 						   sizeof (HOST_WIDE_INT),
166 						   mwi.get_val ()));
167     }
168   return isl_val_int_from_chunks (ctx, wi.get_len (), sizeof (HOST_WIDE_INT),
169 				  wi.get_val ());
170 }
171 
172 /* Extract an affine expression from the gmp constant G.  */
173 
174 static isl_pw_aff *
175 extract_affine_wi (const widest_int &g, __isl_take isl_space *space)
176 {
177   isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
178   isl_aff *aff = isl_aff_zero_on_domain (ls);
179   isl_set *dom = isl_set_universe (space);
180   isl_ctx *ct = isl_aff_get_ctx (aff);
181   isl_val *v = isl_val_int_from_wi (ct, g);
182   aff = isl_aff_add_constant_val (aff, v);
183 
184   return isl_pw_aff_alloc (dom, aff);
185 }
186 
187 /* Extract an affine expression from the integer_cst E.  */
188 
189 static isl_pw_aff *
190 extract_affine_int (tree e, __isl_take isl_space *space)
191 {
192   isl_pw_aff *res = extract_affine_wi (wi::to_widest (e), space);
193   return res;
194 }
195 
196 /* Compute pwaff mod 2^width.  */
197 
198 static isl_pw_aff *
199 wrap (isl_pw_aff *pwaff, unsigned width)
200 {
201   isl_val *mod;
202 
203   mod = isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff), width);
204   mod = isl_val_2exp (mod);
205   pwaff = isl_pw_aff_mod_val (pwaff, mod);
206 
207   return pwaff;
208 }
209 
210 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
211    Otherwise returns -1.  */
212 
213 static inline int
214 parameter_index_in_region_1 (tree name, sese_info_p region)
215 {
216   int i;
217   tree p;
218 
219   gcc_assert (TREE_CODE (name) == SSA_NAME);
220 
221   FOR_EACH_VEC_ELT (region->params, i, p)
222     if (p == name)
223       return i;
224 
225   return -1;
226 }
227 
228 /* Extract an affine expression from the tree E in the scop S.  */
229 
230 static isl_pw_aff *
231 extract_affine (scop_p s, tree e, __isl_take isl_space *space)
232 {
233   isl_pw_aff *lhs, *rhs, *res;
234 
235   if (e == chrec_dont_know) {
236     isl_space_free (space);
237     return NULL;
238   }
239 
240   switch (TREE_CODE (e))
241     {
242     case POLYNOMIAL_CHREC:
243       res = extract_affine_chrec (s, e, space);
244       break;
245 
246     case MULT_EXPR:
247       res = extract_affine_mul (s, e, space);
248       break;
249 
250     case PLUS_EXPR:
251     case POINTER_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 NEGATE_EXPR:
264     case BIT_NOT_EXPR:
265       lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
266       rhs = extract_affine (s, integer_minus_one_node, space);
267       res = isl_pw_aff_mul (lhs, rhs);
268       break;
269 
270     case SSA_NAME:
271       gcc_assert (-1 != parameter_index_in_region_1 (e, s->scop_info)
272 		  || defined_in_sese_p (e, s->scop_info->region));
273       res = extract_affine_name (s, e, space);
274       break;
275 
276     case INTEGER_CST:
277       res = extract_affine_int (e, space);
278       /* No need to wrap a single integer.  */
279       return res;
280 
281     CASE_CONVERT:
282     case NON_LVALUE_EXPR:
283       res = extract_affine (s, TREE_OPERAND (e, 0), space);
284       break;
285 
286     default:
287       gcc_unreachable ();
288       break;
289     }
290 
291   tree type = TREE_TYPE (e);
292   if (TYPE_UNSIGNED (type))
293     res = wrap (res, TYPE_PRECISION (type));
294 
295   return res;
296 }
297 
298 /* Returns a linear expression for tree T evaluated in PBB.  */
299 
300 static isl_pw_aff *
301 create_pw_aff_from_tree (poly_bb_p pbb, loop_p loop, tree t)
302 {
303   scop_p scop = PBB_SCOP (pbb);
304 
305   t = scalar_evolution_in_region (scop->scop_info->region, loop, t);
306 
307   gcc_assert (!chrec_contains_undetermined (t));
308   gcc_assert (!automatically_generated_chrec_p (t));
309 
310   return extract_affine (scop, t, isl_set_get_space (pbb->domain));
311 }
312 
313 /* Add conditional statement STMT to pbb.  CODE is used as the comparison
314    operator.  This allows us to invert the condition or to handle
315    inequalities.  */
316 
317 static void
318 add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code)
319 {
320   loop_p loop = gimple_bb (stmt)->loop_father;
321   isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_lhs (stmt));
322   isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_rhs (stmt));
323 
324   isl_set *cond;
325   switch (code)
326     {
327       case LT_EXPR:
328 	cond = isl_pw_aff_lt_set (lhs, rhs);
329 	break;
330 
331       case GT_EXPR:
332 	cond = isl_pw_aff_gt_set (lhs, rhs);
333 	break;
334 
335       case LE_EXPR:
336 	cond = isl_pw_aff_le_set (lhs, rhs);
337 	break;
338 
339       case GE_EXPR:
340 	cond = isl_pw_aff_ge_set (lhs, rhs);
341 	break;
342 
343       case EQ_EXPR:
344 	cond = isl_pw_aff_eq_set (lhs, rhs);
345 	break;
346 
347       case NE_EXPR:
348 	cond = isl_pw_aff_ne_set (lhs, rhs);
349 	break;
350 
351       default:
352 	gcc_unreachable ();
353     }
354 
355   cond = isl_set_coalesce (cond);
356   cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain));
357   pbb->domain = isl_set_coalesce (isl_set_intersect (pbb->domain, cond));
358 }
359 
360 /* Add conditions to the domain of PBB.  */
361 
362 static void
363 add_conditions_to_domain (poly_bb_p pbb)
364 {
365   unsigned int i;
366   gimple *stmt;
367   gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
368 
369   if (GBB_CONDITIONS (gbb).is_empty ())
370     return;
371 
372   FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
373     switch (gimple_code (stmt))
374       {
375       case GIMPLE_COND:
376 	  {
377             /* Don't constrain on anything else than INTEGER_TYPE.  */
378 	    if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt))) != INTEGER_TYPE)
379               break;
380 
381 	    gcond *cond_stmt = as_a <gcond *> (stmt);
382 	    enum tree_code code = gimple_cond_code (cond_stmt);
383 
384 	    /* The conditions for ELSE-branches are inverted.  */
385 	    if (!GBB_CONDITION_CASES (gbb)[i])
386 	      code = invert_tree_comparison (code, false);
387 
388 	    add_condition_to_pbb (pbb, cond_stmt, code);
389 	    break;
390 	  }
391 
392       default:
393 	gcc_unreachable ();
394 	break;
395       }
396 }
397 
398 /* Add constraints on the possible values of parameter P from the type
399    of P.  */
400 
401 static void
402 add_param_constraints (scop_p scop, graphite_dim_t p)
403 {
404   tree parameter = scop->scop_info->params[p];
405   tree type = TREE_TYPE (parameter);
406   tree lb = NULL_TREE;
407   tree ub = NULL_TREE;
408 
409   if (POINTER_TYPE_P (type) || !TYPE_MIN_VALUE (type))
410     lb = lower_bound_in_type (type, type);
411   else
412     lb = TYPE_MIN_VALUE (type);
413 
414   if (POINTER_TYPE_P (type) || !TYPE_MAX_VALUE (type))
415     ub = upper_bound_in_type (type, type);
416   else
417     ub = TYPE_MAX_VALUE (type);
418 
419   if (lb)
420     {
421       isl_space *space = isl_set_get_space (scop->param_context);
422       isl_constraint *c;
423       isl_val *v;
424 
425       c = isl_inequality_alloc (isl_local_space_from_space (space));
426       v = isl_val_int_from_wi (scop->isl_context, wi::to_widest (lb));
427       v = isl_val_neg (v);
428       c = isl_constraint_set_constant_val (c, v);
429       c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, 1);
430 
431       scop->param_context = isl_set_coalesce
432 	(isl_set_add_constraint (scop->param_context, c));
433     }
434 
435   if (ub)
436     {
437       isl_space *space = isl_set_get_space (scop->param_context);
438       isl_constraint *c;
439       isl_val *v;
440 
441       c = isl_inequality_alloc (isl_local_space_from_space (space));
442 
443       v = isl_val_int_from_wi (scop->isl_context, wi::to_widest (ub));
444       c = isl_constraint_set_constant_val (c, v);
445       c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, -1);
446 
447       scop->param_context = isl_set_coalesce
448 	(isl_set_add_constraint (scop->param_context, c));
449     }
450 }
451 
452 /* Add a constrain to the ACCESSES polyhedron for the alias set of
453    data reference DR.  ACCESSP_NB_DIMS is the dimension of the
454    ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
455    domain.  */
456 
457 static isl_map *
458 pdr_add_alias_set (isl_map *acc, dr_info &dri)
459 {
460   isl_constraint *c = isl_equality_alloc
461       (isl_local_space_from_space (isl_map_get_space (acc)));
462   /* Positive numbers for all alias sets.  */
463   c = isl_constraint_set_constant_si (c, -dri.alias_set);
464   c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
465 
466   return isl_map_add_constraint (acc, c);
467 }
468 
469 /* Add a constrain to the ACCESSES polyhedron for the alias set of
470    data reference DR.  ACCESSP_NB_DIMS is the dimension of the
471    ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
472    domain.  */
473 
474 static isl_map *
475 add_scalar_version_numbers (isl_map *acc, tree var)
476 {
477   isl_constraint *c = isl_equality_alloc
478       (isl_local_space_from_space (isl_map_get_space (acc)));
479   int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP);
480   /* Each scalar variables has a unique alias set number starting from
481      max_arrays.  */
482   c = isl_constraint_set_constant_si (c, -max_arrays - SSA_NAME_VERSION (var));
483   c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
484 
485   return isl_map_add_constraint (acc, c);
486 }
487 
488 /* Assign the affine expression INDEX to the output dimension POS of
489    MAP and return the result.  */
490 
491 static isl_map *
492 set_index (isl_map *map, int pos, isl_pw_aff *index)
493 {
494   isl_map *index_map;
495   int len = isl_map_dim (map, isl_dim_out);
496   isl_id *id;
497 
498   index_map = isl_map_from_pw_aff (index);
499   index_map = isl_map_insert_dims (index_map, isl_dim_out, 0, pos);
500   index_map = isl_map_add_dims (index_map, isl_dim_out, len - pos - 1);
501 
502   id = isl_map_get_tuple_id (map, isl_dim_out);
503   index_map = isl_map_set_tuple_id (index_map, isl_dim_out, id);
504   id = isl_map_get_tuple_id (map, isl_dim_in);
505   index_map = isl_map_set_tuple_id (index_map, isl_dim_in, id);
506 
507   return isl_map_intersect (map, index_map);
508 }
509 
510 /* Add to ACCESSES polyhedron equalities defining the access functions
511    to the memory.  ACCESSP_NB_DIMS is the dimension of the ACCESSES
512    polyhedron, DOM_NB_DIMS is the dimension of the iteration domain.
513    PBB is the poly_bb_p that contains the data reference DR.  */
514 
515 static isl_map *
516 pdr_add_memory_accesses (isl_map *acc, dr_info &dri)
517 {
518   data_reference_p dr = dri.dr;
519   poly_bb_p pbb = dri.pbb;
520   int i, nb_subscripts = DR_NUM_DIMENSIONS (dr);
521   scop_p scop = PBB_SCOP (pbb);
522 
523   for (i = 0; i < nb_subscripts; i++)
524     {
525       isl_pw_aff *aff;
526       tree afn = DR_ACCESS_FN (dr, i);
527 
528       aff = extract_affine (scop, afn,
529 			    isl_space_domain (isl_map_get_space (acc)));
530       acc = set_index (acc, nb_subscripts - i , aff);
531     }
532 
533   return isl_map_coalesce (acc);
534 }
535 
536 /* Return true when the LOW and HIGH bounds of an array reference REF are valid
537    to extract constraints on accessed elements of the array.  Returning false is
538    the conservative answer.  */
539 
540 static bool
541 bounds_are_valid (tree ref, tree low, tree high)
542 {
543   if (!high)
544     return false;
545 
546   if (!tree_fits_shwi_p (low)
547       || !tree_fits_shwi_p (high))
548     return false;
549 
550   /* 1-element arrays at end of structures may extend over
551      their declared size.  */
552   if (array_at_struct_end_p (ref)
553       && operand_equal_p (low, high, 0))
554     return false;
555 
556   /* Fortran has some arrays where high bound is -1 and low is 0.  */
557   if (integer_onep (fold_build2 (LT_EXPR, boolean_type_node, high, low)))
558     return false;
559 
560   return true;
561 }
562 
563 /* Add constrains representing the size of the accessed data to the
564    ACCESSES polyhedron.  ACCESSP_NB_DIMS is the dimension of the
565    ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
566    domain.  */
567 
568 static isl_set *
569 pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop,
570 			 data_reference_p dr)
571 {
572   tree ref = DR_REF (dr);
573 
574   int nb_subscripts = DR_NUM_DIMENSIONS (dr);
575   for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0))
576     {
577       if (TREE_CODE (ref) != ARRAY_REF)
578 	return subscript_sizes;
579 
580       tree low = array_ref_low_bound (ref);
581       tree high = array_ref_up_bound (ref);
582 
583       if (!bounds_are_valid (ref, low, high))
584 	continue;
585 
586       isl_space *space = isl_set_get_space (subscript_sizes);
587       isl_pw_aff *lb = extract_affine_int (low, isl_space_copy (space));
588       isl_pw_aff *ub = extract_affine_int (high, isl_space_copy (space));
589 
590       /* high >= 0 */
591       isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub));
592       valid = isl_set_project_out (valid, isl_dim_set, 0,
593 				   isl_set_dim (valid, isl_dim_set));
594       scop->param_context = isl_set_coalesce
595 	(isl_set_intersect (scop->param_context, valid));
596 
597       isl_aff *aff
598 	= isl_aff_zero_on_domain (isl_local_space_from_space (space));
599       aff = isl_aff_add_coefficient_si (aff, isl_dim_in, i + 1, 1);
600       isl_set *univ
601 	= isl_set_universe (isl_space_domain (isl_aff_get_space (aff)));
602       isl_pw_aff *index = isl_pw_aff_alloc (univ, aff);
603 
604       isl_id *id = isl_set_get_tuple_id (subscript_sizes);
605       lb = isl_pw_aff_set_tuple_id (lb, isl_dim_in, isl_id_copy (id));
606       ub = isl_pw_aff_set_tuple_id (ub, isl_dim_in, id);
607 
608       /* low <= sub_i <= high */
609       isl_set *lbs = isl_pw_aff_ge_set (isl_pw_aff_copy (index), lb);
610       isl_set *ubs = isl_pw_aff_le_set (index, ub);
611       subscript_sizes = isl_set_intersect (subscript_sizes, lbs);
612       subscript_sizes = isl_set_intersect (subscript_sizes, ubs);
613     }
614 
615   return isl_set_coalesce (subscript_sizes);
616 }
617 
618 /* Build data accesses for DRI.  */
619 
620 static void
621 build_poly_dr (dr_info &dri)
622 {
623   isl_map *acc;
624   isl_set *subscript_sizes;
625   poly_bb_p pbb = dri.pbb;
626   data_reference_p dr = dri.dr;
627   scop_p scop = PBB_SCOP (pbb);
628   isl_id *id = isl_id_for_dr (scop);
629 
630   {
631     isl_space *dc = isl_set_get_space (pbb->domain);
632     int nb_out = 1 + DR_NUM_DIMENSIONS (dr);
633     isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
634 					   isl_dim_out, nb_out);
635 
636     acc = isl_map_universe (space);
637     acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id));
638   }
639 
640   acc = pdr_add_alias_set (acc, dri);
641   acc = pdr_add_memory_accesses (acc, dri);
642 
643   {
644     int nb = 1 + DR_NUM_DIMENSIONS (dr);
645     isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb);
646 
647     space = isl_space_set_tuple_id (space, isl_dim_set, id);
648     subscript_sizes = isl_set_nat_universe (space);
649     subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
650 				      dri.alias_set);
651     subscript_sizes = pdr_add_data_dimensions (subscript_sizes, scop, dr);
652   }
653 
654   new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE,
655 	       acc, subscript_sizes);
656 }
657 
658 static void
659 build_poly_sr_1 (poly_bb_p pbb, gimple *stmt, tree var, enum poly_dr_type kind,
660 		 isl_map *acc, isl_set *subscript_sizes)
661 {
662   int max_arrays = PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP);
663   /* Each scalar variables has a unique alias set number starting from
664      max_arrays.  */
665   subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
666 				    max_arrays + SSA_NAME_VERSION (var));
667 
668   new_poly_dr (pbb, stmt, kind, add_scalar_version_numbers (acc, var),
669 	       subscript_sizes);
670 }
671 
672 /* Record all cross basic block scalar variables in PBB.  */
673 
674 static void
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
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 *
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 *
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 = 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
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
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   graphite_dim_t p;
913   for (p = 0; p < nbp; p++)
914     add_param_constraints (scop, p);
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_space *space = isl_set_get_space (iterators);
1047   int loop_index = isl_space_dim (space, isl_dim_set) - 1;
1048 
1049   loop_p ploop = pbb_loop (pbb);
1050   while (loop != ploop)
1051     {
1052       --loop_index;
1053       ploop = loop_outer (ploop);
1054     }
1055 
1056   isl_local_space *ls = isl_local_space_from_space (space);
1057   isl_aff *aff = isl_aff_var_on_domain (ls, isl_dim_set, loop_index);
1058   isl_multi_aff *prefix = isl_multi_aff_from_aff (aff);
1059   char name[50];
1060   snprintf (name, sizeof(name), "L_%d", loop->num);
1061   isl_id *label = isl_id_alloc (isl_schedule_get_ctx (schedule),
1062 				name, NULL);
1063   prefix = isl_multi_aff_set_tuple_id (prefix, isl_dim_out, label);
1064 
1065   int n = isl_multi_aff_dim (prefix, isl_dim_in);
1066   isl_union_set *domain = isl_schedule_get_domain (schedule);
1067   isl_multi_union_pw_aff *mupa = outer_projection_mupa (domain, n);
1068   mupa = isl_multi_union_pw_aff_apply_multi_aff (mupa, prefix);
1069   return isl_schedule_insert_partial_schedule (schedule, mupa);
1070 }
1071 
1072 /* Build schedule for the pbb at INDEX.  */
1073 
1074 static isl_schedule *
1075 build_schedule_pbb (scop_p scop, int *index)
1076 {
1077   poly_bb_p pbb = scop->pbbs[*index];
1078   ++*index;
1079   isl_set *domain = isl_set_copy (pbb->domain);
1080   isl_union_set *ud = isl_union_set_from_set (domain);
1081   return isl_schedule_from_domain (ud);
1082 }
1083 
1084 static isl_schedule *build_schedule_loop_nest (scop_p, int *, loop_p);
1085 
1086 /* Build the schedule of the loop containing the SCOP pbb at INDEX.  */
1087 
1088 static isl_schedule *
1089 build_schedule_loop (scop_p scop, int *index)
1090 {
1091   int max = scop->pbbs.length ();
1092   gcc_assert (*index < max);
1093   loop_p loop = loop_at (scop, index);
1094 
1095   isl_schedule *s = NULL;
1096   while (nested_in (loop_at (scop, index), loop))
1097     {
1098       if (loop == loop_at (scop, index))
1099 	s = add_in_sequence (s, build_schedule_pbb (scop, index));
1100       else
1101 	s = add_in_sequence (s, build_schedule_loop_nest (scop, index, loop));
1102 
1103       if (*index == max)
1104 	break;
1105     }
1106 
1107   return add_loop_schedule (s, loop, scop);
1108 }
1109 
1110 /* S is the schedule of the loop LOOP.  Embed the schedule S in all outer loops.
1111    When CONTEXT_LOOP is null, embed the schedule in all loops contained in the
1112    SCOP surrounding LOOP.  When CONTEXT_LOOP is non null, only embed S in the
1113    maximal loop nest contained within CONTEXT_LOOP.  */
1114 
1115 static isl_schedule *
1116 embed_in_surrounding_loops (__isl_take isl_schedule *s, scop_p scop,
1117 			    loop_p loop, int *index, loop_p context_loop)
1118 {
1119   loop_p outer = loop_outer (loop);
1120   sese_l region = scop->scop_info->region;
1121   if (context_loop == outer
1122       || !loop_in_sese_p (outer, region))
1123     return s;
1124 
1125   int max = scop->pbbs.length ();
1126   if (*index == max
1127       || (context_loop && !nested_in (loop_at (scop, index), context_loop))
1128       || (!context_loop
1129 	  && !loop_in_sese_p (find_common_loop (outer, loop_at (scop, index)),
1130 			      region)))
1131     return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop),
1132 				       scop, outer, index, context_loop);
1133 
1134   bool a_pbb;
1135   while ((a_pbb = (outer == loop_at (scop, index)))
1136 	 || nested_in (loop_at (scop, index), outer))
1137     {
1138       if (a_pbb)
1139 	s = add_in_sequence (s, build_schedule_pbb (scop, index));
1140       else
1141 	s = add_in_sequence (s, build_schedule_loop (scop, index));
1142 
1143       if (*index == max)
1144 	break;
1145     }
1146 
1147   /* We reached the end of the OUTER loop: embed S in OUTER.  */
1148   return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), scop,
1149 				     outer, index, context_loop);
1150 }
1151 
1152 /* Build schedule for the full loop nest containing the pbb at INDEX.  When
1153    CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP
1154    surrounding the pbb.  When CONTEXT_LOOP is non null, only build the maximal loop
1155    nest contained within CONTEXT_LOOP.  */
1156 
1157 static isl_schedule *
1158 build_schedule_loop_nest (scop_p scop, int *index, loop_p context_loop)
1159 {
1160   gcc_assert (*index != (int) scop->pbbs.length ());
1161 
1162   loop_p loop = loop_at (scop, index);
1163   isl_schedule *s = build_schedule_loop (scop, index);
1164   return embed_in_surrounding_loops (s, scop, loop, index, context_loop);
1165 }
1166 
1167 /* Build the schedule of the SCOP.  */
1168 
1169 static bool
1170 build_original_schedule (scop_p scop)
1171 {
1172   int i = 0;
1173   int n = scop->pbbs.length ();
1174   while (i < n)
1175     {
1176       poly_bb_p pbb = scop->pbbs[i];
1177       isl_schedule *s = NULL;
1178       if (!loop_in_sese_p (pbb_loop (pbb), scop->scop_info->region))
1179 	s = build_schedule_pbb (scop, &i);
1180       else
1181 	s = build_schedule_loop_nest (scop, &i, NULL);
1182 
1183       scop->original_schedule = add_in_sequence (scop->original_schedule, s);
1184     }
1185 
1186   if (dump_file)
1187     {
1188       fprintf (dump_file, "[sese-to-poly] original schedule:\n");
1189       print_isl_schedule (dump_file, scop->original_schedule);
1190     }
1191   if (!scop->original_schedule)
1192     return false;
1193   return true;
1194 }
1195 
1196 /* Builds the polyhedral representation for a SESE region.  */
1197 
1198 bool
1199 build_poly_scop (scop_p scop)
1200 {
1201   build_scop_context (scop);
1202 
1203   unsigned i = 0;
1204   unsigned n = scop->pbbs.length ();
1205   while (i < n)
1206     i = build_iteration_domains (scop, scop->param_context, i, NULL);
1207 
1208   build_scop_drs (scop);
1209   build_original_schedule (scop);
1210   return true;
1211 }
1212 #endif  /* HAVE_isl */
1213