]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/graphite-sese-to-poly.c
graphite.h: Do not include isl/isl_val_gmp.h, instead include isl/isl_val.h.
[thirdparty/gcc.git] / gcc / graphite-sese-to-poly.c
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 */