1 /* Conversion of SESE regions to Polyhedra.
2 Copyright (C) 2009-2018 Free Software Foundation, Inc.
3 Contributed by Sebastian Pop <sebastian.pop@amd.com>.
5 This file is part of GCC.
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)
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.
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/>. */
28 #include "coretypes.h"
35 #include "fold-const.h"
36 #include "gimple-iterator.h"
38 #include "gimplify-me.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"
46 #include "tree-data-ref.h"
47 #include "tree-scalar-evolution.h"
49 #include "tree-ssa-propagate.h"
51 #include <isl/constraint.h>
54 #include <isl/union_map.h>
55 #include <isl/constraint.h>
61 /* Return an isl identifier for the polyhedral basic block PBB. */
64 isl_id_for_pbb (scop_p s
, poly_bb_p pbb
)
67 snprintf (name
, sizeof (name
), "S_%d", pbb_index (pbb
));
68 return isl_id_alloc (s
->isl_context
, name
, pbb
);
71 static isl_pw_aff
*extract_affine (scop_p
, tree
, __isl_take isl_space
*space
);
73 /* Extract an affine expression from the chain of recurrence E. */
76 extract_affine_chrec (scop_p s
, tree e
, __isl_take isl_space
*space
)
78 isl_pw_aff
*lhs
= extract_affine (s
, CHREC_LEFT (e
), isl_space_copy (space
));
79 isl_pw_aff
*rhs
= extract_affine (s
, CHREC_RIGHT (e
), isl_space_copy (space
));
80 isl_local_space
*ls
= isl_local_space_from_space (space
);
81 unsigned pos
= sese_loop_depth (s
->scop_info
->region
, get_chrec_loop (e
)) - 1;
82 isl_aff
*loop
= isl_aff_set_coefficient_si
83 (isl_aff_zero_on_domain (ls
), isl_dim_in
, pos
, 1);
84 isl_pw_aff
*l
= isl_pw_aff_from_aff (loop
);
86 /* Before multiplying, make sure that the result is affine. */
87 gcc_assert (isl_pw_aff_is_cst (rhs
)
88 || isl_pw_aff_is_cst (l
));
90 return isl_pw_aff_add (lhs
, isl_pw_aff_mul (rhs
, l
));
93 /* Extract an affine expression from the mult_expr E. */
96 extract_affine_mul (scop_p s
, tree e
, __isl_take isl_space
*space
)
98 isl_pw_aff
*lhs
= extract_affine (s
, TREE_OPERAND (e
, 0),
99 isl_space_copy (space
));
100 isl_pw_aff
*rhs
= extract_affine (s
, TREE_OPERAND (e
, 1), space
);
102 if (!isl_pw_aff_is_cst (lhs
)
103 && !isl_pw_aff_is_cst (rhs
))
105 isl_pw_aff_free (lhs
);
106 isl_pw_aff_free (rhs
);
110 return isl_pw_aff_mul (lhs
, rhs
);
113 /* Return an isl identifier from the name of the ssa_name E. */
116 isl_id_for_ssa_name (scop_p s
, tree e
)
119 snprintf (name1
, sizeof (name1
), "P_%d", SSA_NAME_VERSION (e
));
120 return isl_id_alloc (s
->isl_context
, name1
, e
);
123 /* Return an isl identifier for the data reference DR. Data references and
124 scalar references get the same isl_id. They need to be comparable and are
125 distinguished through the first dimension, which contains the alias set or
126 SSA_NAME_VERSION number. */
129 isl_id_for_dr (scop_p s
)
131 return isl_id_alloc (s
->isl_context
, "", 0);
134 /* Extract an affine expression from the ssa_name E. */
137 extract_affine_name (int dimension
, __isl_take isl_space
*space
)
139 isl_set
*dom
= isl_set_universe (isl_space_copy (space
));
140 isl_aff
*aff
= isl_aff_zero_on_domain (isl_local_space_from_space (space
));
141 aff
= isl_aff_add_coefficient_si (aff
, isl_dim_param
, dimension
, 1);
142 return isl_pw_aff_alloc (dom
, aff
);
145 /* Convert WI to a isl_val with CTX. */
147 static __isl_give isl_val
*
148 isl_val_int_from_wi (isl_ctx
*ctx
, const widest_int
&wi
)
150 if (wi::neg_p (wi
, SIGNED
))
152 widest_int mwi
= -wi
;
153 return isl_val_neg (isl_val_int_from_chunks (ctx
, mwi
.get_len (),
154 sizeof (HOST_WIDE_INT
),
157 return isl_val_int_from_chunks (ctx
, wi
.get_len (), sizeof (HOST_WIDE_INT
),
161 /* Extract an affine expression from the gmp constant G. */
164 extract_affine_wi (const widest_int
&g
, __isl_take isl_space
*space
)
166 isl_local_space
*ls
= isl_local_space_from_space (isl_space_copy (space
));
167 isl_aff
*aff
= isl_aff_zero_on_domain (ls
);
168 isl_set
*dom
= isl_set_universe (space
);
169 isl_ctx
*ct
= isl_aff_get_ctx (aff
);
170 isl_val
*v
= isl_val_int_from_wi (ct
, g
);
171 aff
= isl_aff_add_constant_val (aff
, v
);
173 return isl_pw_aff_alloc (dom
, aff
);
176 /* Extract an affine expression from the integer_cst E. */
179 extract_affine_int (tree e
, __isl_take isl_space
*space
)
181 isl_pw_aff
*res
= extract_affine_wi (wi::to_widest (e
), space
);
185 /* Compute pwaff mod 2^width. */
188 wrap (isl_pw_aff
*pwaff
, unsigned width
)
192 mod
= isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff
), width
);
193 mod
= isl_val_2exp (mod
);
194 pwaff
= isl_pw_aff_mod_val (pwaff
, mod
);
199 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
200 Otherwise returns -1. */
203 parameter_index_in_region (tree name
, sese_info_p region
)
207 FOR_EACH_VEC_ELT (region
->params
, i
, p
)
213 /* Extract an affine expression from the tree E in the scop S. */
216 extract_affine (scop_p s
, tree e
, __isl_take isl_space
*space
)
218 isl_pw_aff
*lhs
, *rhs
, *res
;
220 if (e
== chrec_dont_know
) {
221 isl_space_free (space
);
225 tree type
= TREE_TYPE (e
);
226 switch (TREE_CODE (e
))
228 case POLYNOMIAL_CHREC
:
229 res
= extract_affine_chrec (s
, e
, space
);
233 res
= extract_affine_mul (s
, e
, space
);
236 case POINTER_PLUS_EXPR
:
238 lhs
= extract_affine (s
, TREE_OPERAND (e
, 0), isl_space_copy (space
));
239 /* The RHS of a pointer-plus expression is to be interpreted
240 as signed value. Try to look through a sign-changing conversion
242 tree tem
= TREE_OPERAND (e
, 1);
244 rhs
= extract_affine (s
, tem
, space
);
245 if (TYPE_UNSIGNED (TREE_TYPE (tem
)))
246 rhs
= wrap (rhs
, TYPE_PRECISION (type
) - 1);
247 res
= isl_pw_aff_add (lhs
, rhs
);
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
);
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
);
264 lhs
= extract_affine (s
, integer_minus_one_node
, isl_space_copy (space
));
265 rhs
= extract_affine (s
, TREE_OPERAND (e
, 0), space
);
266 res
= isl_pw_aff_sub (lhs
, rhs
);
267 /* We need to always wrap the result of a bitwise operation. */
268 return wrap (res
, TYPE_PRECISION (type
) - (TYPE_UNSIGNED (type
) ? 0 : 1));
271 lhs
= extract_affine (s
, TREE_OPERAND (e
, 0), isl_space_copy (space
));
272 rhs
= extract_affine (s
, integer_minus_one_node
, space
);
273 res
= isl_pw_aff_mul (lhs
, rhs
);
278 gcc_assert (! defined_in_sese_p (e
, s
->scop_info
->region
));
279 int dim
= parameter_index_in_region (e
, s
->scop_info
);
280 gcc_assert (dim
!= -1);
281 /* No need to wrap a parameter. */
282 return extract_affine_name (dim
, space
);
286 res
= extract_affine_int (e
, space
);
287 /* No need to wrap a single integer. */
292 tree itype
= TREE_TYPE (TREE_OPERAND (e
, 0));
293 res
= extract_affine (s
, TREE_OPERAND (e
, 0), space
);
294 /* Signed values, even if overflow is undefined, get modulo-reduced.
295 But only if not all values of the old type fit in the new. */
296 if (! TYPE_UNSIGNED (type
)
297 && ((TYPE_UNSIGNED (itype
)
298 && TYPE_PRECISION (type
) <= TYPE_PRECISION (itype
))
299 || TYPE_PRECISION (type
) < TYPE_PRECISION (itype
)))
300 res
= wrap (res
, TYPE_PRECISION (type
) - 1);
301 else if (TYPE_UNSIGNED (type
)
302 && (!TYPE_UNSIGNED (itype
)
303 || TYPE_PRECISION (type
) < TYPE_PRECISION (itype
)))
304 res
= wrap (res
, TYPE_PRECISION (type
));
308 case NON_LVALUE_EXPR
:
309 res
= extract_affine (s
, TREE_OPERAND (e
, 0), space
);
317 /* For all wrapping arithmetic wrap the result. */
318 if (TYPE_OVERFLOW_WRAPS (type
))
319 res
= wrap (res
, TYPE_PRECISION (type
));
324 /* Returns a linear expression for tree T evaluated in PBB. */
327 create_pw_aff_from_tree (poly_bb_p pbb
, loop_p loop
, tree t
)
329 scop_p scop
= PBB_SCOP (pbb
);
331 t
= scalar_evolution_in_region (scop
->scop_info
->region
, loop
, t
);
333 gcc_assert (!chrec_contains_undetermined (t
));
334 gcc_assert (!automatically_generated_chrec_p (t
));
336 return extract_affine (scop
, t
, isl_set_get_space (pbb
->domain
));
339 /* Add conditional statement STMT to pbb. CODE is used as the comparison
340 operator. This allows us to invert the condition or to handle
344 add_condition_to_pbb (poly_bb_p pbb
, gcond
*stmt
, enum tree_code code
)
346 loop_p loop
= gimple_bb (stmt
)->loop_father
;
347 isl_pw_aff
*lhs
= create_pw_aff_from_tree (pbb
, loop
, gimple_cond_lhs (stmt
));
348 isl_pw_aff
*rhs
= create_pw_aff_from_tree (pbb
, loop
, gimple_cond_rhs (stmt
));
354 cond
= isl_pw_aff_lt_set (lhs
, rhs
);
358 cond
= isl_pw_aff_gt_set (lhs
, rhs
);
362 cond
= isl_pw_aff_le_set (lhs
, rhs
);
366 cond
= isl_pw_aff_ge_set (lhs
, rhs
);
370 cond
= isl_pw_aff_eq_set (lhs
, rhs
);
374 cond
= isl_pw_aff_ne_set (lhs
, rhs
);
381 cond
= isl_set_coalesce (cond
);
382 cond
= isl_set_set_tuple_id (cond
, isl_set_get_tuple_id (pbb
->domain
));
383 pbb
->domain
= isl_set_coalesce (isl_set_intersect (pbb
->domain
, cond
));
386 /* Add conditions to the domain of PBB. */
389 add_conditions_to_domain (poly_bb_p pbb
)
393 gimple_poly_bb_p gbb
= PBB_BLACK_BOX (pbb
);
395 if (GBB_CONDITIONS (gbb
).is_empty ())
398 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb
), i
, stmt
)
399 switch (gimple_code (stmt
))
403 /* Don't constrain on anything else than INTEGER_TYPE. */
404 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt
))) != INTEGER_TYPE
)
407 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
408 enum tree_code code
= gimple_cond_code (cond_stmt
);
410 /* The conditions for ELSE-branches are inverted. */
411 if (!GBB_CONDITION_CASES (gbb
)[i
])
412 code
= invert_tree_comparison (code
, false);
414 add_condition_to_pbb (pbb
, cond_stmt
, code
);
424 /* Add constraints on the possible values of parameter P from the type
428 add_param_constraints (scop_p scop
, graphite_dim_t p
, tree parameter
)
430 tree type
= TREE_TYPE (parameter
);
433 gcc_assert (INTEGRAL_TYPE_P (type
) || POINTER_TYPE_P (type
));
435 if (INTEGRAL_TYPE_P (type
)
436 && get_range_info (parameter
, &min
, &max
) == VR_RANGE
)
440 min
= wi::min_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
441 max
= wi::max_value (TYPE_PRECISION (type
), TYPE_SIGN (type
));
444 isl_space
*space
= isl_set_get_space (scop
->param_context
);
445 isl_constraint
*c
= isl_inequality_alloc (isl_local_space_from_space (space
));
446 isl_val
*v
= isl_val_int_from_wi (scop
->isl_context
,
447 widest_int::from (min
, TYPE_SIGN (type
)));
449 c
= isl_constraint_set_constant_val (c
, v
);
450 c
= isl_constraint_set_coefficient_si (c
, isl_dim_param
, p
, 1);
451 scop
->param_context
= isl_set_coalesce
452 (isl_set_add_constraint (scop
->param_context
, c
));
454 space
= isl_set_get_space (scop
->param_context
);
455 c
= isl_inequality_alloc (isl_local_space_from_space (space
));
456 v
= isl_val_int_from_wi (scop
->isl_context
,
457 widest_int::from (max
, TYPE_SIGN (type
)));
458 c
= isl_constraint_set_constant_val (c
, v
);
459 c
= isl_constraint_set_coefficient_si (c
, isl_dim_param
, p
, -1);
460 scop
->param_context
= isl_set_coalesce
461 (isl_set_add_constraint (scop
->param_context
, c
));
464 /* Add a constrain to the ACCESSES polyhedron for the alias set of
465 data reference DR. ACCESSP_NB_DIMS is the dimension of the
466 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
470 pdr_add_alias_set (isl_map
*acc
, dr_info
&dri
)
472 isl_constraint
*c
= isl_equality_alloc
473 (isl_local_space_from_space (isl_map_get_space (acc
)));
474 /* Positive numbers for all alias sets. */
475 c
= isl_constraint_set_constant_si (c
, -dri
.alias_set
);
476 c
= isl_constraint_set_coefficient_si (c
, isl_dim_out
, 0, 1);
478 return isl_map_add_constraint (acc
, c
);
481 /* Assign the affine expression INDEX to the output dimension POS of
482 MAP and return the result. */
485 set_index (isl_map
*map
, int pos
, isl_pw_aff
*index
)
488 int len
= isl_map_dim (map
, isl_dim_out
);
491 index_map
= isl_map_from_pw_aff (index
);
492 index_map
= isl_map_insert_dims (index_map
, isl_dim_out
, 0, pos
);
493 index_map
= isl_map_add_dims (index_map
, isl_dim_out
, len
- pos
- 1);
495 id
= isl_map_get_tuple_id (map
, isl_dim_out
);
496 index_map
= isl_map_set_tuple_id (index_map
, isl_dim_out
, id
);
497 id
= isl_map_get_tuple_id (map
, isl_dim_in
);
498 index_map
= isl_map_set_tuple_id (index_map
, isl_dim_in
, id
);
500 return isl_map_intersect (map
, index_map
);
503 /* Add to ACCESSES polyhedron equalities defining the access functions
504 to the memory. ACCESSP_NB_DIMS is the dimension of the ACCESSES
505 polyhedron, DOM_NB_DIMS is the dimension of the iteration domain.
506 PBB is the poly_bb_p that contains the data reference DR. */
509 pdr_add_memory_accesses (isl_map
*acc
, dr_info
&dri
)
511 data_reference_p dr
= dri
.dr
;
512 poly_bb_p pbb
= dri
.pbb
;
513 int i
, nb_subscripts
= DR_NUM_DIMENSIONS (dr
);
514 scop_p scop
= PBB_SCOP (pbb
);
516 for (i
= 0; i
< nb_subscripts
; i
++)
519 tree afn
= DR_ACCESS_FN (dr
, i
);
521 aff
= extract_affine (scop
, afn
,
522 isl_space_domain (isl_map_get_space (acc
)));
523 acc
= set_index (acc
, nb_subscripts
- i
, aff
);
526 return isl_map_coalesce (acc
);
529 /* Return true when the LOW and HIGH bounds of an array reference REF are valid
530 to extract constraints on accessed elements of the array. Returning false is
531 the conservative answer. */
534 bounds_are_valid (tree ref
, tree low
, tree high
)
539 if (!tree_fits_shwi_p (low
)
540 || !tree_fits_shwi_p (high
))
543 /* 1-element arrays at end of structures may extend over
544 their declared size. */
545 if (array_at_struct_end_p (ref
)
546 && operand_equal_p (low
, high
, 0))
549 /* Fortran has some arrays where high bound is -1 and low is 0. */
550 if (integer_onep (fold_build2 (LT_EXPR
, boolean_type_node
, high
, low
)))
556 /* Add constrains representing the size of the accessed data to the
557 ACCESSES polyhedron. ACCESSP_NB_DIMS is the dimension of the
558 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
562 pdr_add_data_dimensions (isl_set
*subscript_sizes
, scop_p scop
,
565 tree ref
= DR_REF (dr
);
567 int nb_subscripts
= DR_NUM_DIMENSIONS (dr
);
568 for (int i
= nb_subscripts
- 1; i
>= 0; i
--, ref
= TREE_OPERAND (ref
, 0))
570 if (TREE_CODE (ref
) != ARRAY_REF
)
571 return subscript_sizes
;
573 tree low
= array_ref_low_bound (ref
);
574 tree high
= array_ref_up_bound (ref
);
576 if (!bounds_are_valid (ref
, low
, high
))
579 isl_space
*space
= isl_set_get_space (subscript_sizes
);
580 isl_pw_aff
*lb
= extract_affine_int (low
, isl_space_copy (space
));
581 isl_pw_aff
*ub
= extract_affine_int (high
, isl_space_copy (space
));
584 isl_set
*valid
= isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub
));
585 valid
= isl_set_project_out (valid
, isl_dim_set
, 0,
586 isl_set_dim (valid
, isl_dim_set
));
587 scop
->param_context
= isl_set_coalesce
588 (isl_set_intersect (scop
->param_context
, valid
));
591 = isl_aff_zero_on_domain (isl_local_space_from_space (space
));
592 aff
= isl_aff_add_coefficient_si (aff
, isl_dim_in
, i
+ 1, 1);
594 = isl_set_universe (isl_space_domain (isl_aff_get_space (aff
)));
595 isl_pw_aff
*index
= isl_pw_aff_alloc (univ
, aff
);
597 isl_id
*id
= isl_set_get_tuple_id (subscript_sizes
);
598 lb
= isl_pw_aff_set_tuple_id (lb
, isl_dim_in
, isl_id_copy (id
));
599 ub
= isl_pw_aff_set_tuple_id (ub
, isl_dim_in
, id
);
601 /* low <= sub_i <= high */
602 isl_set
*lbs
= isl_pw_aff_ge_set (isl_pw_aff_copy (index
), lb
);
603 isl_set
*ubs
= isl_pw_aff_le_set (index
, ub
);
604 subscript_sizes
= isl_set_intersect (subscript_sizes
, lbs
);
605 subscript_sizes
= isl_set_intersect (subscript_sizes
, ubs
);
608 return isl_set_coalesce (subscript_sizes
);
611 /* Build data accesses for DRI. */
614 build_poly_dr (dr_info
&dri
)
617 isl_set
*subscript_sizes
;
618 poly_bb_p pbb
= dri
.pbb
;
619 data_reference_p dr
= dri
.dr
;
620 scop_p scop
= PBB_SCOP (pbb
);
621 isl_id
*id
= isl_id_for_dr (scop
);
624 isl_space
*dc
= isl_set_get_space (pbb
->domain
);
625 int nb_out
= 1 + DR_NUM_DIMENSIONS (dr
);
626 isl_space
*space
= isl_space_add_dims (isl_space_from_domain (dc
),
627 isl_dim_out
, nb_out
);
629 acc
= isl_map_universe (space
);
630 acc
= isl_map_set_tuple_id (acc
, isl_dim_out
, isl_id_copy (id
));
633 acc
= pdr_add_alias_set (acc
, dri
);
634 acc
= pdr_add_memory_accesses (acc
, dri
);
637 int nb
= 1 + DR_NUM_DIMENSIONS (dr
);
638 isl_space
*space
= isl_space_set_alloc (scop
->isl_context
, 0, nb
);
640 space
= isl_space_set_tuple_id (space
, isl_dim_set
, id
);
641 subscript_sizes
= isl_set_nat_universe (space
);
642 subscript_sizes
= isl_set_fix_si (subscript_sizes
, isl_dim_set
, 0,
644 subscript_sizes
= pdr_add_data_dimensions (subscript_sizes
, scop
, dr
);
647 new_poly_dr (pbb
, DR_STMT (dr
), DR_IS_READ (dr
) ? PDR_READ
: PDR_WRITE
,
648 acc
, subscript_sizes
);
652 build_poly_sr_1 (poly_bb_p pbb
, gimple
*stmt
, tree var
, enum poly_dr_type kind
,
653 isl_map
*acc
, isl_set
*subscript_sizes
)
655 scop_p scop
= PBB_SCOP (pbb
);
656 /* Each scalar variables has a unique alias set number starting from
657 the maximum alias set assigned to a dr. */
658 int alias_set
= scop
->max_alias_set
+ SSA_NAME_VERSION (var
);
659 subscript_sizes
= isl_set_fix_si (subscript_sizes
, isl_dim_set
, 0,
662 /* Add a constrain to the ACCESSES polyhedron for the alias set of
663 data reference DR. */
665 = isl_equality_alloc (isl_local_space_from_space (isl_map_get_space (acc
)));
666 c
= isl_constraint_set_constant_si (c
, -alias_set
);
667 c
= isl_constraint_set_coefficient_si (c
, isl_dim_out
, 0, 1);
669 new_poly_dr (pbb
, stmt
, kind
, isl_map_add_constraint (acc
, c
),
673 /* Record all cross basic block scalar variables in PBB. */
676 build_poly_sr (poly_bb_p pbb
)
678 scop_p scop
= PBB_SCOP (pbb
);
679 gimple_poly_bb_p gbb
= PBB_BLACK_BOX (pbb
);
680 vec
<scalar_use
> &reads
= gbb
->read_scalar_refs
;
681 vec
<tree
> &writes
= gbb
->write_scalar_refs
;
683 isl_space
*dc
= isl_set_get_space (pbb
->domain
);
685 isl_space
*space
= isl_space_add_dims (isl_space_from_domain (dc
),
686 isl_dim_out
, nb_out
);
687 isl_id
*id
= isl_id_for_dr (scop
);
688 space
= isl_space_set_tuple_id (space
, isl_dim_set
, isl_id_copy (id
));
689 isl_map
*acc
= isl_map_universe (isl_space_copy (space
));
690 acc
= isl_map_set_tuple_id (acc
, isl_dim_out
, id
);
691 isl_set
*subscript_sizes
= isl_set_nat_universe (space
);
695 FOR_EACH_VEC_ELT (writes
, i
, var
)
696 build_poly_sr_1 (pbb
, SSA_NAME_DEF_STMT (var
), var
, PDR_WRITE
,
697 isl_map_copy (acc
), isl_set_copy (subscript_sizes
));
700 FOR_EACH_VEC_ELT (reads
, i
, use
)
701 build_poly_sr_1 (pbb
, use
->first
, use
->second
, PDR_READ
, isl_map_copy (acc
),
702 isl_set_copy (subscript_sizes
));
705 isl_set_free (subscript_sizes
);
708 /* Build data references in SCOP. */
711 build_scop_drs (scop_p scop
)
715 FOR_EACH_VEC_ELT (scop
->drs
, i
, dri
)
716 build_poly_dr (*dri
);
719 FOR_EACH_VEC_ELT (scop
->pbbs
, i
, pbb
)
723 /* Add to the iteration DOMAIN one extra dimension for LOOP->num. */
726 add_iter_domain_dimension (__isl_take isl_set
*domain
, loop_p loop
, scop_p scop
)
728 int loop_index
= isl_set_dim (domain
, isl_dim_set
);
729 domain
= isl_set_add_dims (domain
, isl_dim_set
, 1);
731 snprintf (name
, sizeof(name
), "i%d", loop
->num
);
732 isl_id
*label
= isl_id_alloc (scop
->isl_context
, name
, NULL
);
733 return isl_set_set_dim_id (domain
, isl_dim_set
, loop_index
, label
);
736 /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */
739 add_loop_constraints (scop_p scop
, __isl_take isl_set
*domain
, loop_p loop
,
744 const sese_l
®ion
= scop
->scop_info
->region
;
745 if (!loop_in_sese_p (loop
, region
))
748 /* Recursion all the way up to the context loop. */
749 domain
= add_loop_constraints (scop
, domain
, loop_outer (loop
), context
);
751 /* Then, build constraints over the loop in post-order: outer to inner. */
753 int loop_index
= isl_set_dim (domain
, isl_dim_set
);
755 fprintf (dump_file
, "[sese-to-poly] adding one extra dimension to the "
756 "domain for loop_%d.\n", loop
->num
);
757 domain
= add_iter_domain_dimension (domain
, loop
, scop
);
758 isl_space
*space
= isl_set_get_space (domain
);
761 isl_local_space
*ls
= isl_local_space_from_space (isl_space_copy (space
));
762 isl_constraint
*c
= isl_inequality_alloc (ls
);
763 c
= isl_constraint_set_coefficient_si (c
, isl_dim_set
, loop_index
, 1);
766 fprintf (dump_file
, "[sese-to-poly] adding constraint to the domain: ");
767 print_isl_constraint (dump_file
, c
);
769 domain
= isl_set_add_constraint (domain
, c
);
771 tree nb_iters
= number_of_latch_executions (loop
);
772 if (TREE_CODE (nb_iters
) == INTEGER_CST
)
774 /* loop_i <= cst_nb_iters */
775 isl_local_space
*ls
= isl_local_space_from_space (space
);
776 isl_constraint
*c
= isl_inequality_alloc (ls
);
777 c
= isl_constraint_set_coefficient_si (c
, isl_dim_set
, loop_index
, -1);
779 = isl_val_int_from_wi (scop
->isl_context
, wi::to_widest (nb_iters
));
780 c
= isl_constraint_set_constant_val (c
, v
);
781 return isl_set_add_constraint (domain
, c
);
783 /* loop_i <= expr_nb_iters */
784 gcc_assert (!chrec_contains_undetermined (nb_iters
));
785 nb_iters
= scalar_evolution_in_region (region
, loop
, nb_iters
);
786 gcc_assert (!chrec_contains_undetermined (nb_iters
));
788 isl_pw_aff
*aff_nb_iters
= extract_affine (scop
, nb_iters
,
789 isl_space_copy (space
));
790 isl_set
*valid
= isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters
));
791 valid
= isl_set_project_out (valid
, isl_dim_set
, 0,
792 isl_set_dim (valid
, isl_dim_set
));
795 scop
->param_context
= isl_set_intersect (scop
->param_context
, valid
);
797 ls
= isl_local_space_from_space (isl_space_copy (space
));
798 isl_aff
*loop_i
= isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls
),
799 isl_dim_in
, loop_index
, 1);
800 isl_set
*le
= isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i
),
801 isl_pw_aff_copy (aff_nb_iters
));
804 fprintf (dump_file
, "[sese-to-poly] adding constraint to the domain: ");
805 print_isl_set (dump_file
, le
);
807 domain
= isl_set_intersect (domain
, le
);
810 if (!max_stmt_executions (loop
, &nit
))
812 isl_pw_aff_free (aff_nb_iters
);
813 isl_space_free (space
);
817 /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we
818 do not know whether the loop executes at least once. */
821 isl_pw_aff
*approx
= extract_affine_wi (nit
, isl_space_copy (space
));
822 isl_set
*x
= isl_pw_aff_ge_set (approx
, aff_nb_iters
);
823 x
= isl_set_project_out (x
, isl_dim_set
, 0,
824 isl_set_dim (x
, isl_dim_set
));
825 scop
->param_context
= isl_set_intersect (scop
->param_context
, x
);
827 ls
= isl_local_space_from_space (space
);
828 c
= isl_inequality_alloc (ls
);
829 c
= isl_constraint_set_coefficient_si (c
, isl_dim_set
, loop_index
, -1);
830 isl_val
*v
= isl_val_int_from_wi (scop
->isl_context
, nit
);
831 c
= isl_constraint_set_constant_val (c
, v
);
835 fprintf (dump_file
, "[sese-to-poly] adding constraint to the domain: ");
836 print_isl_constraint (dump_file
, c
);
839 return isl_set_add_constraint (domain
, c
);
842 /* Builds the original iteration domains for each pbb in the SCOP. */
845 build_iteration_domains (scop_p scop
, __isl_keep isl_set
*context
,
846 int index
, loop_p context_loop
)
848 loop_p current
= pbb_loop (scop
->pbbs
[index
]);
849 isl_set
*domain
= isl_set_copy (context
);
850 domain
= add_loop_constraints (scop
, domain
, current
, context_loop
);
851 const sese_l
®ion
= scop
->scop_info
->region
;
855 FOR_EACH_VEC_ELT_FROM (scop
->pbbs
, i
, pbb
, index
)
857 loop_p loop
= pbb_loop (pbb
);
860 pbb
->iterators
= isl_set_copy (domain
);
861 pbb
->domain
= isl_set_copy (domain
);
862 pbb
->domain
= isl_set_set_tuple_id (pbb
->domain
,
863 isl_id_for_pbb (scop
, pbb
));
864 add_conditions_to_domain (pbb
);
868 fprintf (dump_file
, "[sese-to-poly] set pbb_%d->domain: ",
870 print_isl_set (dump_file
, domain
);
875 while (loop_in_sese_p (loop
, region
)
877 loop
= loop_outer (loop
);
881 /* A statement in a different loop nest than CURRENT loop. */
882 isl_set_free (domain
);
886 /* A statement nested in the CURRENT loop. */
887 i
= build_iteration_domains (scop
, domain
, i
, current
);
891 isl_set_free (domain
);
895 /* Assign dimension for each parameter in SCOP and add constraints for the
899 build_scop_context (scop_p scop
)
901 sese_info_p region
= scop
->scop_info
;
902 unsigned nbp
= sese_nb_params (region
);
903 isl_space
*space
= isl_space_set_alloc (scop
->isl_context
, nbp
, 0);
907 FOR_EACH_VEC_ELT (region
->params
, i
, e
)
908 space
= isl_space_set_dim_id (space
, isl_dim_param
, i
,
909 isl_id_for_ssa_name (scop
, e
));
911 scop
->param_context
= isl_set_universe (space
);
913 FOR_EACH_VEC_ELT (region
->params
, i
, e
)
914 add_param_constraints (scop
, i
, e
);
917 /* Return true when loop A is nested in loop B. */
920 nested_in (loop_p a
, loop_p b
)
922 return b
== find_common_loop (a
, b
);
925 /* Return the loop at a specific SCOP->pbbs[*INDEX]. */
927 loop_at (scop_p scop
, int *index
)
929 return pbb_loop (scop
->pbbs
[*index
]);
932 /* Return the index of any pbb belonging to loop or a subloop of A. */
935 index_outermost_in_loop (loop_p a
, scop_p scop
)
937 int i
, outermost
= -1;
940 FOR_EACH_VEC_ELT (scop
->pbbs
, i
, pbb
)
941 if (nested_in (pbb_loop (pbb
), a
)
943 || last_depth
> (int) loop_depth (pbb_loop (pbb
))))
946 last_depth
= loop_depth (pbb_loop (pbb
));
951 /* Return the index of any pbb belonging to loop or a subloop of A. */
954 index_pbb_in_loop (loop_p a
, scop_p scop
)
958 FOR_EACH_VEC_ELT (scop
->pbbs
, i
, pbb
)
959 if (pbb_loop (pbb
) == a
)
965 outermost_pbb_in (loop_p loop
, scop_p scop
)
967 int x
= index_pbb_in_loop (loop
, scop
);
969 x
= index_outermost_in_loop (loop
, scop
);
970 return scop
->pbbs
[x
];
973 static isl_schedule
*
974 add_in_sequence (__isl_take isl_schedule
*a
, __isl_take isl_schedule
*b
)
984 return isl_schedule_sequence (a
, b
);
987 struct map_to_dimension_data
{
989 isl_union_pw_multi_aff
*res
;
992 /* Create a function that maps the elements of SET to its N-th dimension and add
996 add_outer_projection (__isl_take isl_set
*set
, void *user
)
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
);
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
,
1006 data
->res
= isl_union_pw_multi_aff_add_pw_multi_aff (data
->res
, pma
);
1012 /* Return SET in which all inner dimensions above N are removed. */
1014 static isl_multi_union_pw_aff
*
1015 outer_projection_mupa (__isl_take isl_union_set
*set
, int n
)
1017 gcc_assert (n
>= 0);
1019 gcc_assert (!isl_union_set_is_empty (set
));
1021 isl_space
*space
= isl_union_set_get_space (set
);
1022 isl_union_pw_multi_aff
*pwaff
= isl_union_pw_multi_aff_empty (space
);
1024 struct map_to_dimension_data data
= {n
, pwaff
};
1026 if (isl_union_set_foreach_set (set
, &add_outer_projection
, &data
) < 0)
1027 data
.res
= isl_union_pw_multi_aff_free (data
.res
);
1029 isl_union_set_free (set
);
1030 return isl_multi_union_pw_aff_from_union_pw_multi_aff (data
.res
);
1033 /* Embed SCHEDULE in the constraints of the LOOP domain. */
1035 static isl_schedule
*
1036 add_loop_schedule (__isl_take isl_schedule
*schedule
, loop_p loop
,
1039 poly_bb_p pbb
= outermost_pbb_in (loop
, scop
);
1040 isl_set
*iterators
= pbb
->iterators
;
1042 int empty
= isl_set_is_empty (iterators
);
1043 if (empty
< 0 || empty
)
1044 return empty
< 0 ? isl_schedule_free (schedule
) : schedule
;
1046 isl_union_set
*domain
= isl_schedule_get_domain (schedule
);
1047 /* We cannot apply an empty domain to pbbs in this loop so return early. */
1048 if (isl_union_set_is_empty (domain
))
1050 isl_union_set_free (domain
);
1054 isl_space
*space
= isl_set_get_space (iterators
);
1055 int loop_index
= isl_space_dim (space
, isl_dim_set
) - 1;
1057 loop_p ploop
= pbb_loop (pbb
);
1058 while (loop
!= ploop
)
1061 ploop
= loop_outer (ploop
);
1064 isl_local_space
*ls
= isl_local_space_from_space (space
);
1065 isl_aff
*aff
= isl_aff_var_on_domain (ls
, isl_dim_set
, loop_index
);
1066 isl_multi_aff
*prefix
= isl_multi_aff_from_aff (aff
);
1068 snprintf (name
, sizeof(name
), "L_%d", loop
->num
);
1069 isl_id
*label
= isl_id_alloc (isl_schedule_get_ctx (schedule
),
1071 prefix
= isl_multi_aff_set_tuple_id (prefix
, isl_dim_out
, label
);
1073 int n
= isl_multi_aff_dim (prefix
, isl_dim_in
);
1074 isl_multi_union_pw_aff
*mupa
= outer_projection_mupa (domain
, n
);
1075 mupa
= isl_multi_union_pw_aff_apply_multi_aff (mupa
, prefix
);
1076 return isl_schedule_insert_partial_schedule (schedule
, mupa
);
1079 /* Build schedule for the pbb at INDEX. */
1081 static isl_schedule
*
1082 build_schedule_pbb (scop_p scop
, int *index
)
1084 poly_bb_p pbb
= scop
->pbbs
[*index
];
1086 isl_set
*domain
= isl_set_copy (pbb
->domain
);
1087 isl_union_set
*ud
= isl_union_set_from_set (domain
);
1088 return isl_schedule_from_domain (ud
);
1091 static isl_schedule
*build_schedule_loop_nest (scop_p
, int *, loop_p
);
1093 /* Build the schedule of the loop containing the SCOP pbb at INDEX. */
1095 static isl_schedule
*
1096 build_schedule_loop (scop_p scop
, int *index
)
1098 int max
= scop
->pbbs
.length ();
1099 gcc_assert (*index
< max
);
1100 loop_p loop
= loop_at (scop
, index
);
1102 isl_schedule
*s
= NULL
;
1103 while (nested_in (loop_at (scop
, index
), loop
))
1105 if (loop
== loop_at (scop
, index
))
1106 s
= add_in_sequence (s
, build_schedule_pbb (scop
, index
));
1108 s
= add_in_sequence (s
, build_schedule_loop_nest (scop
, index
, loop
));
1114 return add_loop_schedule (s
, loop
, scop
);
1117 /* S is the schedule of the loop LOOP. Embed the schedule S in all outer loops.
1118 When CONTEXT_LOOP is null, embed the schedule in all loops contained in the
1119 SCOP surrounding LOOP. When CONTEXT_LOOP is non null, only embed S in the
1120 maximal loop nest contained within CONTEXT_LOOP. */
1122 static isl_schedule
*
1123 embed_in_surrounding_loops (__isl_take isl_schedule
*s
, scop_p scop
,
1124 loop_p loop
, int *index
, loop_p context_loop
)
1126 loop_p outer
= loop_outer (loop
);
1127 sese_l region
= scop
->scop_info
->region
;
1128 if (context_loop
== outer
1129 || !loop_in_sese_p (outer
, region
))
1132 int max
= scop
->pbbs
.length ();
1134 || (context_loop
&& !nested_in (loop_at (scop
, index
), context_loop
))
1136 && !loop_in_sese_p (find_common_loop (outer
, loop_at (scop
, index
)),
1138 return embed_in_surrounding_loops (add_loop_schedule (s
, outer
, scop
),
1139 scop
, outer
, index
, context_loop
);
1142 while ((a_pbb
= (outer
== loop_at (scop
, index
)))
1143 || nested_in (loop_at (scop
, index
), outer
))
1146 s
= add_in_sequence (s
, build_schedule_pbb (scop
, index
));
1148 s
= add_in_sequence (s
, build_schedule_loop (scop
, index
));
1154 /* We reached the end of the OUTER loop: embed S in OUTER. */
1155 return embed_in_surrounding_loops (add_loop_schedule (s
, outer
, scop
), scop
,
1156 outer
, index
, context_loop
);
1159 /* Build schedule for the full loop nest containing the pbb at INDEX. When
1160 CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP
1161 surrounding the pbb. When CONTEXT_LOOP is non null, only build the maximal loop
1162 nest contained within CONTEXT_LOOP. */
1164 static isl_schedule
*
1165 build_schedule_loop_nest (scop_p scop
, int *index
, loop_p context_loop
)
1167 gcc_assert (*index
!= (int) scop
->pbbs
.length ());
1169 loop_p loop
= loop_at (scop
, index
);
1170 isl_schedule
*s
= build_schedule_loop (scop
, index
);
1171 return embed_in_surrounding_loops (s
, scop
, loop
, index
, context_loop
);
1174 /* Build the schedule of the SCOP. */
1177 build_original_schedule (scop_p scop
)
1180 int n
= scop
->pbbs
.length ();
1183 poly_bb_p pbb
= scop
->pbbs
[i
];
1184 isl_schedule
*s
= NULL
;
1185 if (!loop_in_sese_p (pbb_loop (pbb
), scop
->scop_info
->region
))
1186 s
= build_schedule_pbb (scop
, &i
);
1188 s
= build_schedule_loop_nest (scop
, &i
, NULL
);
1190 scop
->original_schedule
= add_in_sequence (scop
->original_schedule
, s
);
1195 fprintf (dump_file
, "[sese-to-poly] original schedule:\n");
1196 print_isl_schedule (dump_file
, scop
->original_schedule
);
1200 /* Builds the polyhedral representation for a SESE region. */
1203 build_poly_scop (scop_p scop
)
1205 int old_err
= isl_options_get_on_error (scop
->isl_context
);
1206 isl_options_set_on_error (scop
->isl_context
, ISL_ON_ERROR_CONTINUE
);
1208 build_scop_context (scop
);
1211 unsigned n
= scop
->pbbs
.length ();
1213 i
= build_iteration_domains (scop
, scop
->param_context
, i
, NULL
);
1215 build_scop_drs (scop
);
1216 build_original_schedule (scop
);
1218 enum isl_error err
= isl_ctx_last_error (scop
->isl_context
);
1219 isl_ctx_reset_error (scop
->isl_context
);
1220 isl_options_set_on_error (scop
->isl_context
, old_err
);
1221 if (err
!= isl_error_none
)
1222 dump_printf (MSG_MISSED_OPTIMIZATION
,
1223 "ISL error while building poly scop\n");
1225 return err
== isl_error_none
;
1227 #endif /* HAVE_isl */