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>.
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 /* Assigns to RES the value of the INTEGER_CST T. */
64 tree_int_to_gmp (tree t
, mpz_t res
)
66 wi::to_mpz (t
, res
, TYPE_SIGN (TREE_TYPE (t
)));
69 /* Return an isl identifier for the polyhedral basic block PBB. */
72 isl_id_for_pbb (scop_p s
, poly_bb_p pbb
)
75 snprintf (name
, sizeof (name
), "S_%d", pbb_index (pbb
));
76 return isl_id_alloc (s
->isl_context
, name
, pbb
);
79 static isl_pw_aff
*extract_affine (scop_p
, tree
, __isl_take isl_space
*space
);
81 /* Extract an affine expression from the chain of recurrence E. */
84 extract_affine_chrec (scop_p s
, tree e
, __isl_take isl_space
*space
)
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
);
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
));
98 return isl_pw_aff_add (lhs
, isl_pw_aff_mul (rhs
, l
));
101 /* Extract an affine expression from the mult_expr E. */
104 extract_affine_mul (scop_p s
, tree e
, __isl_take isl_space
*space
)
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
);
110 if (!isl_pw_aff_is_cst (lhs
)
111 && !isl_pw_aff_is_cst (rhs
))
113 isl_pw_aff_free (lhs
);
114 isl_pw_aff_free (rhs
);
118 return isl_pw_aff_mul (lhs
, rhs
);
121 /* Return an isl identifier from the name of the ssa_name E. */
124 isl_id_for_ssa_name (scop_p s
, tree e
)
127 snprintf (name1
, sizeof (name1
), "P_%d", SSA_NAME_VERSION (e
));
128 return isl_id_alloc (s
->isl_context
, name1
, e
);
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. */
137 isl_id_for_dr (scop_p s
)
139 return isl_id_alloc (s
->isl_context
, "", 0);
142 /* Extract an affine expression from the ssa_name E. */
145 extract_affine_name (scop_p s
, tree e
, __isl_take isl_space
*space
)
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
);
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
);
156 /* Convert WI to a isl_val with CTX. */
158 static __isl_give isl_val
*
159 isl_val_int_from_wi (isl_ctx
*ctx
, const widest_int
&wi
)
161 if (wi::neg_p (wi
, SIGNED
))
163 widest_int mwi
= -wi
;
164 return isl_val_neg (isl_val_int_from_chunks (ctx
, mwi
.get_len (),
165 sizeof (HOST_WIDE_INT
),
168 return isl_val_int_from_chunks (ctx
, wi
.get_len (), sizeof (HOST_WIDE_INT
),
172 /* Extract an affine expression from the gmp constant G. */
175 extract_affine_wi (const widest_int
&g
, __isl_take isl_space
*space
)
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
);
184 return isl_pw_aff_alloc (dom
, aff
);
187 /* Extract an affine expression from the integer_cst E. */
190 extract_affine_int (tree e
, __isl_take isl_space
*space
)
192 isl_pw_aff
*res
= extract_affine_wi (wi::to_widest (e
), space
);
196 /* Compute pwaff mod 2^width. */
199 wrap (isl_pw_aff
*pwaff
, unsigned width
)
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
);
210 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
211 Otherwise returns -1. */
214 parameter_index_in_region_1 (tree name
, sese_info_p region
)
219 gcc_assert (TREE_CODE (name
) == SSA_NAME
);
221 FOR_EACH_VEC_ELT (region
->params
, i
, p
)
228 /* Extract an affine expression from the tree E in the scop S. */
231 extract_affine (scop_p s
, tree e
, __isl_take isl_space
*space
)
233 isl_pw_aff
*lhs
, *rhs
, *res
;
235 if (e
== chrec_dont_know
) {
236 isl_space_free (space
);
240 switch (TREE_CODE (e
))
242 case POLYNOMIAL_CHREC
:
243 res
= extract_affine_chrec (s
, e
, space
);
247 res
= extract_affine_mul (s
, e
, space
);
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
);
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
);
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
);
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
);
277 res
= extract_affine_int (e
, space
);
278 /* No need to wrap a single integer. */
282 case NON_LVALUE_EXPR
:
283 res
= extract_affine (s
, TREE_OPERAND (e
, 0), space
);
291 tree type
= TREE_TYPE (e
);
292 if (TYPE_UNSIGNED (type
))
293 res
= wrap (res
, TYPE_PRECISION (type
));
298 /* Returns a linear expression for tree T evaluated in PBB. */
301 create_pw_aff_from_tree (poly_bb_p pbb
, loop_p loop
, tree t
)
303 scop_p scop
= PBB_SCOP (pbb
);
305 t
= scalar_evolution_in_region (scop
->scop_info
->region
, loop
, t
);
307 gcc_assert (!chrec_contains_undetermined (t
));
308 gcc_assert (!automatically_generated_chrec_p (t
));
310 return extract_affine (scop
, t
, isl_set_get_space (pbb
->domain
));
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
318 add_condition_to_pbb (poly_bb_p pbb
, gcond
*stmt
, enum tree_code code
)
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
));
328 cond
= isl_pw_aff_lt_set (lhs
, rhs
);
332 cond
= isl_pw_aff_gt_set (lhs
, rhs
);
336 cond
= isl_pw_aff_le_set (lhs
, rhs
);
340 cond
= isl_pw_aff_ge_set (lhs
, rhs
);
344 cond
= isl_pw_aff_eq_set (lhs
, rhs
);
348 cond
= isl_pw_aff_ne_set (lhs
, rhs
);
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
));
360 /* Add conditions to the domain of PBB. */
363 add_conditions_to_domain (poly_bb_p pbb
)
367 gimple_poly_bb_p gbb
= PBB_BLACK_BOX (pbb
);
369 if (GBB_CONDITIONS (gbb
).is_empty ())
372 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb
), i
, stmt
)
373 switch (gimple_code (stmt
))
377 /* Don't constrain on anything else than INTEGER_TYPE. */
378 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt
))) != INTEGER_TYPE
)
381 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
382 enum tree_code code
= gimple_cond_code (cond_stmt
);
384 /* The conditions for ELSE-branches are inverted. */
385 if (!GBB_CONDITION_CASES (gbb
)[i
])
386 code
= invert_tree_comparison (code
, false);
388 add_condition_to_pbb (pbb
, cond_stmt
, code
);
398 /* Add constraints on the possible values of parameter P from the type
402 add_param_constraints (scop_p scop
, graphite_dim_t p
)
404 tree parameter
= scop
->scop_info
->params
[p
];
405 tree type
= TREE_TYPE (parameter
);
409 if (POINTER_TYPE_P (type
) || !TYPE_MIN_VALUE (type
))
410 lb
= lower_bound_in_type (type
, type
);
412 lb
= TYPE_MIN_VALUE (type
);
414 if (POINTER_TYPE_P (type
) || !TYPE_MAX_VALUE (type
))
415 ub
= upper_bound_in_type (type
, type
);
417 ub
= TYPE_MAX_VALUE (type
);
421 isl_space
*space
= isl_set_get_space (scop
->param_context
);
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
));
428 c
= isl_constraint_set_constant_val (c
, v
);
429 c
= isl_constraint_set_coefficient_si (c
, isl_dim_param
, p
, 1);
431 scop
->param_context
= isl_set_coalesce
432 (isl_set_add_constraint (scop
->param_context
, c
));
437 isl_space
*space
= isl_set_get_space (scop
->param_context
);
441 c
= isl_inequality_alloc (isl_local_space_from_space (space
));
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);
447 scop
->param_context
= isl_set_coalesce
448 (isl_set_add_constraint (scop
->param_context
, c
));
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
458 pdr_add_alias_set (isl_map
*acc
, dr_info
&dri
)
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);
466 return isl_map_add_constraint (acc
, c
);
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
475 add_scalar_version_numbers (isl_map
*acc
, tree var
)
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
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);
485 return isl_map_add_constraint (acc
, c
);
488 /* Assign the affine expression INDEX to the output dimension POS of
489 MAP and return the result. */
492 set_index (isl_map
*map
, int pos
, isl_pw_aff
*index
)
495 int len
= isl_map_dim (map
, isl_dim_out
);
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);
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
);
507 return isl_map_intersect (map
, index_map
);
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. */
516 pdr_add_memory_accesses (isl_map
*acc
, dr_info
&dri
)
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
);
523 for (i
= 0; i
< nb_subscripts
; i
++)
526 tree afn
= DR_ACCESS_FN (dr
, i
);
528 aff
= extract_affine (scop
, afn
,
529 isl_space_domain (isl_map_get_space (acc
)));
530 acc
= set_index (acc
, nb_subscripts
- i
, aff
);
533 return isl_map_coalesce (acc
);
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. */
541 bounds_are_valid (tree ref
, tree low
, tree high
)
546 if (!tree_fits_shwi_p (low
)
547 || !tree_fits_shwi_p (high
))
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))
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
)))
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
569 pdr_add_data_dimensions (isl_set
*subscript_sizes
, scop_p scop
,
572 tree ref
= DR_REF (dr
);
574 int nb_subscripts
= DR_NUM_DIMENSIONS (dr
);
575 for (int i
= nb_subscripts
- 1; i
>= 0; i
--, ref
= TREE_OPERAND (ref
, 0))
577 if (TREE_CODE (ref
) != ARRAY_REF
)
578 return subscript_sizes
;
580 tree low
= array_ref_low_bound (ref
);
581 tree high
= array_ref_up_bound (ref
);
583 if (!bounds_are_valid (ref
, low
, high
))
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
));
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
));
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);
601 = isl_set_universe (isl_space_domain (isl_aff_get_space (aff
)));
602 isl_pw_aff
*index
= isl_pw_aff_alloc (univ
, aff
);
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
);
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
);
615 return isl_set_coalesce (subscript_sizes
);
618 /* Build data accesses for DRI. */
621 build_poly_dr (dr_info
&dri
)
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
);
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
);
636 acc
= isl_map_universe (space
);
637 acc
= isl_map_set_tuple_id (acc
, isl_dim_out
, isl_id_copy (id
));
640 acc
= pdr_add_alias_set (acc
, dri
);
641 acc
= pdr_add_memory_accesses (acc
, dri
);
644 int nb
= 1 + DR_NUM_DIMENSIONS (dr
);
645 isl_space
*space
= isl_space_set_alloc (scop
->isl_context
, 0, nb
);
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,
651 subscript_sizes
= pdr_add_data_dimensions (subscript_sizes
, scop
, dr
);
654 new_poly_dr (pbb
, DR_STMT (dr
), DR_IS_READ (dr
) ? PDR_READ
: PDR_WRITE
,
655 acc
, subscript_sizes
);
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
)
662 int max_arrays
= PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP
);
663 /* Each scalar variables has a unique alias set number starting from
665 subscript_sizes
= isl_set_fix_si (subscript_sizes
, isl_dim_set
, 0,
666 max_arrays
+ SSA_NAME_VERSION (var
));
668 new_poly_dr (pbb
, stmt
, kind
, add_scalar_version_numbers (acc
, var
),
672 /* Record all cross basic block scalar variables in PBB. */
675 build_poly_sr (poly_bb_p pbb
)
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
;
682 isl_space
*dc
= isl_set_get_space (pbb
->domain
);
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
);
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
));
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
));
704 isl_set_free (subscript_sizes
);
707 /* Build data references in SCOP. */
710 build_scop_drs (scop_p scop
)
714 FOR_EACH_VEC_ELT (scop
->drs
, i
, dri
)
715 build_poly_dr (*dri
);
718 FOR_EACH_VEC_ELT (scop
->pbbs
, i
, pbb
)
722 /* Add to the iteration DOMAIN one extra dimension for LOOP->num. */
725 add_iter_domain_dimension (__isl_take isl_set
*domain
, loop_p loop
, scop_p scop
)
727 int loop_index
= isl_set_dim (domain
, isl_dim_set
);
728 domain
= isl_set_add_dims (domain
, isl_dim_set
, 1);
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
);
735 /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */
738 add_loop_constraints (scop_p scop
, __isl_take isl_set
*domain
, loop_p loop
,
743 const sese_l
®ion
= scop
->scop_info
->region
;
744 if (!loop_in_sese_p (loop
, region
))
747 /* Recursion all the way up to the context loop. */
748 domain
= add_loop_constraints (scop
, domain
, loop_outer (loop
), context
);
750 /* Then, build constraints over the loop in post-order: outer to inner. */
752 int loop_index
= isl_set_dim (domain
, isl_dim_set
);
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
);
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);
765 fprintf (dump_file
, "[sese-to-poly] adding constraint to the domain: ");
766 print_isl_constraint (dump_file
, c
);
768 domain
= isl_set_add_constraint (domain
, c
);
770 tree nb_iters
= number_of_latch_executions (loop
);
771 if (TREE_CODE (nb_iters
) == INTEGER_CST
)
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);
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
);
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
));
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
));
794 scop
->param_context
= isl_set_intersect (scop
->param_context
, valid
);
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
));
803 fprintf (dump_file
, "[sese-to-poly] adding constraint to the domain: ");
804 print_isl_set (dump_file
, le
);
806 domain
= isl_set_intersect (domain
, le
);
809 if (!max_stmt_executions (loop
, &nit
))
811 isl_pw_aff_free (aff_nb_iters
);
812 isl_space_free (space
);
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. */
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
);
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
);
834 fprintf (dump_file
, "[sese-to-poly] adding constraint to the domain: ");
835 print_isl_constraint (dump_file
, c
);
838 return isl_set_add_constraint (domain
, c
);
841 /* Builds the original iteration domains for each pbb in the SCOP. */
844 build_iteration_domains (scop_p scop
, __isl_keep isl_set
*context
,
845 int index
, loop_p context_loop
)
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
®ion
= scop
->scop_info
->region
;
854 FOR_EACH_VEC_ELT_FROM (scop
->pbbs
, i
, pbb
, index
)
856 loop_p loop
= pbb_loop (pbb
);
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
);
867 fprintf (dump_file
, "[sese-to-poly] set pbb_%d->domain: ",
869 print_isl_set (dump_file
, domain
);
874 while (loop_in_sese_p (loop
, region
)
876 loop
= loop_outer (loop
);
880 /* A statement in a different loop nest than CURRENT loop. */
881 isl_set_free (domain
);
885 /* A statement nested in the CURRENT loop. */
886 i
= build_iteration_domains (scop
, domain
, i
, current
);
890 isl_set_free (domain
);
894 /* Assign dimension for each parameter in SCOP and add constraints for the
898 build_scop_context (scop_p scop
)
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);
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
));
910 scop
->param_context
= isl_set_universe (space
);
913 for (p
= 0; p
< nbp
; p
++)
914 add_param_constraints (scop
, p
);
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_space
*space
= isl_set_get_space (iterators
);
1047 int loop_index
= isl_space_dim (space
, isl_dim_set
) - 1;
1049 loop_p ploop
= pbb_loop (pbb
);
1050 while (loop
!= ploop
)
1053 ploop
= loop_outer (ploop
);
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
);
1060 snprintf (name
, sizeof(name
), "L_%d", loop
->num
);
1061 isl_id
*label
= isl_id_alloc (isl_schedule_get_ctx (schedule
),
1063 prefix
= isl_multi_aff_set_tuple_id (prefix
, isl_dim_out
, label
);
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
);
1072 /* Build schedule for the pbb at INDEX. */
1074 static isl_schedule
*
1075 build_schedule_pbb (scop_p scop
, int *index
)
1077 poly_bb_p pbb
= scop
->pbbs
[*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
);
1084 static isl_schedule
*build_schedule_loop_nest (scop_p
, int *, loop_p
);
1086 /* Build the schedule of the loop containing the SCOP pbb at INDEX. */
1088 static isl_schedule
*
1089 build_schedule_loop (scop_p scop
, int *index
)
1091 int max
= scop
->pbbs
.length ();
1092 gcc_assert (*index
< max
);
1093 loop_p loop
= loop_at (scop
, index
);
1095 isl_schedule
*s
= NULL
;
1096 while (nested_in (loop_at (scop
, index
), loop
))
1098 if (loop
== loop_at (scop
, index
))
1099 s
= add_in_sequence (s
, build_schedule_pbb (scop
, index
));
1101 s
= add_in_sequence (s
, build_schedule_loop_nest (scop
, index
, loop
));
1107 return add_loop_schedule (s
, loop
, scop
);
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. */
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
)
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
))
1125 int max
= scop
->pbbs
.length ();
1127 || (context_loop
&& !nested_in (loop_at (scop
, index
), context_loop
))
1129 && !loop_in_sese_p (find_common_loop (outer
, loop_at (scop
, index
)),
1131 return embed_in_surrounding_loops (add_loop_schedule (s
, outer
, scop
),
1132 scop
, outer
, index
, context_loop
);
1135 while ((a_pbb
= (outer
== loop_at (scop
, index
)))
1136 || nested_in (loop_at (scop
, index
), outer
))
1139 s
= add_in_sequence (s
, build_schedule_pbb (scop
, index
));
1141 s
= add_in_sequence (s
, build_schedule_loop (scop
, index
));
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
);
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. */
1157 static isl_schedule
*
1158 build_schedule_loop_nest (scop_p scop
, int *index
, loop_p context_loop
)
1160 gcc_assert (*index
!= (int) scop
->pbbs
.length ());
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
);
1167 /* Build the schedule of the SCOP. */
1170 build_original_schedule (scop_p scop
)
1173 int n
= scop
->pbbs
.length ();
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
);
1181 s
= build_schedule_loop_nest (scop
, &i
, NULL
);
1183 scop
->original_schedule
= add_in_sequence (scop
->original_schedule
, s
);
1188 fprintf (dump_file
, "[sese-to-poly] original schedule:\n");
1189 print_isl_schedule (dump_file
, scop
->original_schedule
);
1191 if (!scop
->original_schedule
)
1196 /* Builds the polyhedral representation for a SESE region. */
1199 build_poly_scop (scop_p scop
)
1201 build_scop_context (scop
);
1204 unsigned n
= scop
->pbbs
.length ();
1206 i
= build_iteration_domains (scop
, scop
->param_context
, i
, NULL
);
1208 build_scop_drs (scop
);
1209 build_original_schedule (scop
);
1212 #endif /* HAVE_isl */