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