1 /* Conversion of SESE regions to Polyhedra.
2 Copyright (C) 2009-2016 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>
58 #include <isl/val_gmp.h>
62 /* Assigns to RES the value of the INTEGER_CST T. */
65 tree_int_to_gmp (tree t
, mpz_t res
)
67 wi::to_mpz (t
, res
, TYPE_SIGN (TREE_TYPE (t
)));
70 /* Return an isl identifier for the polyhedral basic block PBB. */
73 isl_id_for_pbb (scop_p s
, poly_bb_p pbb
)
76 snprintf (name
, sizeof (name
), "S_%d", pbb_index (pbb
));
77 return isl_id_alloc (s
->isl_context
, name
, pbb
);
80 #ifndef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
81 /* Converts the STATIC_SCHEDULE of PBB into a scattering polyhedron.
82 We generate SCATTERING_DIMENSIONS scattering dimensions.
84 The scattering polyhedron consists of these dimensions: scattering,
85 loop_iterators, parameters.
89 | scattering_dimensions = 5
97 | Scattering polyhedron:
99 | scattering: {s1, s2, s3, s4, s5}
100 | loop_iterators: {i}
101 | parameters: {p1, p2}
103 | s1 s2 s3 s4 s5 i p1 p2 1
104 | 1 0 0 0 0 0 0 0 -4 = 0
105 | 0 1 0 0 0 -1 0 0 0 = 0
106 | 0 0 1 0 0 0 0 0 -5 = 0 */
109 build_pbb_scattering_polyhedrons (isl_aff
*static_sched
,
114 int scattering_dimensions
= isl_set_dim (pbb
->domain
, isl_dim_set
) * 2 + 1;
116 isl_space
*dc
= isl_set_get_space (pbb
->domain
);
117 isl_space
*dm
= isl_space_add_dims (isl_space_from_domain (dc
),
118 isl_dim_out
, scattering_dimensions
);
119 pbb
->schedule
= isl_map_universe (dm
);
121 for (int i
= 0; i
< scattering_dimensions
; i
++)
123 /* Textual order inside this loop. */
126 isl_constraint
*c
= isl_equality_alloc
127 (isl_local_space_from_space (isl_map_get_space (pbb
->schedule
)));
129 val
= isl_aff_get_coefficient_val (static_sched
, isl_dim_in
, i
/ 2);
130 gcc_assert (val
&& isl_val_is_int (val
));
132 val
= isl_val_neg (val
);
133 c
= isl_constraint_set_constant_val (c
, val
);
134 c
= isl_constraint_set_coefficient_si (c
, isl_dim_out
, i
, 1);
135 pbb
->schedule
= isl_map_add_constraint (pbb
->schedule
, c
);
138 /* Iterations of this loop. */
139 else /* if ((i % 2) == 1) */
141 int loop
= (i
- 1) / 2;
142 pbb
->schedule
= isl_map_equate (pbb
->schedule
, isl_dim_in
, loop
,
147 /* Simplify the original schedule. */
148 pbb
->schedule
= isl_map_coalesce (pbb
->schedule
);
150 /* At the beginning, set the transformed schedule to the original. */
151 pbb
->transformed
= isl_map_copy (pbb
->schedule
);
154 /* Build for BB the static schedule.
156 The static schedule is a Dewey numbering of the abstract syntax
157 tree: http://en.wikipedia.org/wiki/Dewey_Decimal_Classification
159 The following example informally defines the static schedule:
178 Static schedules for A to F:
191 build_scop_scattering (scop_p scop
)
193 gimple_poly_bb_p previous_gbb
= NULL
;
194 isl_space
*dc
= isl_set_get_space (scop
->param_context
);
195 isl_aff
*static_sched
;
197 dc
= isl_space_add_dims (dc
, isl_dim_set
, number_of_loops (cfun
));
198 static_sched
= isl_aff_zero_on_domain (isl_local_space_from_space (dc
));
200 /* We have to start schedules at 0 on the first component and
201 because we cannot compare_prefix_loops against a previous loop,
202 prefix will be equal to zero, and that index will be
203 incremented before copying. */
204 static_sched
= isl_aff_add_coefficient_si (static_sched
, isl_dim_in
, 0, -1);
208 FOR_EACH_VEC_ELT (scop
->pbbs
, i
, pbb
)
210 gimple_poly_bb_p gbb
= PBB_BLACK_BOX (pbb
);
214 prefix
= nb_common_loops (scop
->scop_info
->region
, previous_gbb
, gbb
);
218 static_sched
= isl_aff_add_coefficient_si (static_sched
, isl_dim_in
,
220 build_pbb_scattering_polyhedrons (static_sched
, pbb
);
223 isl_aff_free (static_sched
);
227 static isl_pw_aff
*extract_affine (scop_p
, tree
, __isl_take isl_space
*space
);
229 /* Extract an affine expression from the chain of recurrence E. */
232 extract_affine_chrec (scop_p s
, tree e
, __isl_take isl_space
*space
)
234 isl_pw_aff
*lhs
= extract_affine (s
, CHREC_LEFT (e
), isl_space_copy (space
));
235 isl_pw_aff
*rhs
= extract_affine (s
, CHREC_RIGHT (e
), isl_space_copy (space
));
236 isl_local_space
*ls
= isl_local_space_from_space (space
);
237 unsigned pos
= sese_loop_depth (s
->scop_info
->region
, get_chrec_loop (e
)) - 1;
238 isl_aff
*loop
= isl_aff_set_coefficient_si
239 (isl_aff_zero_on_domain (ls
), isl_dim_in
, pos
, 1);
240 isl_pw_aff
*l
= isl_pw_aff_from_aff (loop
);
242 /* Before multiplying, make sure that the result is affine. */
243 gcc_assert (isl_pw_aff_is_cst (rhs
)
244 || isl_pw_aff_is_cst (l
));
246 return isl_pw_aff_add (lhs
, isl_pw_aff_mul (rhs
, l
));
249 /* Extract an affine expression from the mult_expr E. */
252 extract_affine_mul (scop_p s
, tree e
, __isl_take isl_space
*space
)
254 isl_pw_aff
*lhs
= extract_affine (s
, TREE_OPERAND (e
, 0),
255 isl_space_copy (space
));
256 isl_pw_aff
*rhs
= extract_affine (s
, TREE_OPERAND (e
, 1), space
);
258 if (!isl_pw_aff_is_cst (lhs
)
259 && !isl_pw_aff_is_cst (rhs
))
261 isl_pw_aff_free (lhs
);
262 isl_pw_aff_free (rhs
);
266 return isl_pw_aff_mul (lhs
, rhs
);
269 /* Return an isl identifier from the name of the ssa_name E. */
272 isl_id_for_ssa_name (scop_p s
, tree e
)
275 snprintf (name1
, sizeof (name1
), "P_%d", SSA_NAME_VERSION (e
));
276 return isl_id_alloc (s
->isl_context
, name1
, e
);
279 /* Return an isl identifier for the data reference DR. Data references and
280 scalar references get the same isl_id. They need to be comparable and are
281 distinguished through the first dimension, which contains the alias set or
282 SSA_NAME_VERSION number. */
285 isl_id_for_dr (scop_p s
)
287 return isl_id_alloc (s
->isl_context
, "", 0);
290 /* Extract an affine expression from the ssa_name E. */
293 extract_affine_name (scop_p s
, tree e
, __isl_take isl_space
*space
)
295 isl_id
*id
= isl_id_for_ssa_name (s
, e
);
296 int dimension
= isl_space_find_dim_by_id (space
, isl_dim_param
, id
);
298 isl_set
*dom
= isl_set_universe (isl_space_copy (space
));
299 isl_aff
*aff
= isl_aff_zero_on_domain (isl_local_space_from_space (space
));
300 aff
= isl_aff_add_coefficient_si (aff
, isl_dim_param
, dimension
, 1);
301 return isl_pw_aff_alloc (dom
, aff
);
304 /* Extract an affine expression from the gmp constant G. */
307 extract_affine_gmp (mpz_t g
, __isl_take isl_space
*space
)
309 isl_local_space
*ls
= isl_local_space_from_space (isl_space_copy (space
));
310 isl_aff
*aff
= isl_aff_zero_on_domain (ls
);
311 isl_set
*dom
= isl_set_universe (space
);
312 isl_ctx
*ct
= isl_aff_get_ctx (aff
);
313 isl_val
*v
= isl_val_int_from_gmp (ct
, g
);
314 aff
= isl_aff_add_constant_val (aff
, v
);
316 return isl_pw_aff_alloc (dom
, aff
);
319 /* Extract an affine expression from the integer_cst E. */
322 extract_affine_int (tree e
, __isl_take isl_space
*space
)
327 tree_int_to_gmp (e
, g
);
328 isl_pw_aff
*res
= extract_affine_gmp (g
, space
);
334 /* Compute pwaff mod 2^width. */
337 wrap (isl_pw_aff
*pwaff
, unsigned width
)
341 mod
= isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff
), width
);
342 mod
= isl_val_2exp (mod
);
343 pwaff
= isl_pw_aff_mod_val (pwaff
, mod
);
348 /* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
349 Otherwise returns -1. */
352 parameter_index_in_region_1 (tree name
, sese_info_p region
)
357 gcc_assert (TREE_CODE (name
) == SSA_NAME
);
359 FOR_EACH_VEC_ELT (region
->params
, i
, p
)
366 /* Extract an affine expression from the tree E in the scop S. */
369 extract_affine (scop_p s
, tree e
, __isl_take isl_space
*space
)
371 isl_pw_aff
*lhs
, *rhs
, *res
;
373 if (e
== chrec_dont_know
) {
374 isl_space_free (space
);
378 switch (TREE_CODE (e
))
380 case POLYNOMIAL_CHREC
:
381 res
= extract_affine_chrec (s
, e
, space
);
385 res
= extract_affine_mul (s
, e
, space
);
389 case POINTER_PLUS_EXPR
:
390 lhs
= extract_affine (s
, TREE_OPERAND (e
, 0), isl_space_copy (space
));
391 rhs
= extract_affine (s
, TREE_OPERAND (e
, 1), space
);
392 res
= isl_pw_aff_add (lhs
, rhs
);
396 lhs
= extract_affine (s
, TREE_OPERAND (e
, 0), isl_space_copy (space
));
397 rhs
= extract_affine (s
, TREE_OPERAND (e
, 1), space
);
398 res
= isl_pw_aff_sub (lhs
, rhs
);
403 lhs
= extract_affine (s
, TREE_OPERAND (e
, 0), isl_space_copy (space
));
404 rhs
= extract_affine (s
, integer_minus_one_node
, space
);
405 res
= isl_pw_aff_mul (lhs
, rhs
);
409 gcc_assert (-1 != parameter_index_in_region_1 (e
, s
->scop_info
)
410 || !invariant_in_sese_p_rec (e
, s
->scop_info
->region
, NULL
));
411 res
= extract_affine_name (s
, e
, space
);
415 res
= extract_affine_int (e
, space
);
416 /* No need to wrap a single integer. */
420 case NON_LVALUE_EXPR
:
421 res
= extract_affine (s
, TREE_OPERAND (e
, 0), space
);
429 tree type
= TREE_TYPE (e
);
430 if (TYPE_UNSIGNED (type
))
431 res
= wrap (res
, TYPE_PRECISION (type
));
436 /* Returns a linear expression for tree T evaluated in PBB. */
439 create_pw_aff_from_tree (poly_bb_p pbb
, tree t
)
441 scop_p scop
= PBB_SCOP (pbb
);
443 t
= scalar_evolution_in_region (scop
->scop_info
->region
, pbb_loop (pbb
), t
);
445 gcc_assert (!chrec_contains_undetermined (t
));
446 gcc_assert (!automatically_generated_chrec_p (t
));
448 return extract_affine (scop
, t
, isl_set_get_space (pbb
->domain
));
451 /* Add conditional statement STMT to pbb. CODE is used as the comparison
452 operator. This allows us to invert the condition or to handle
456 add_condition_to_pbb (poly_bb_p pbb
, gcond
*stmt
, enum tree_code code
)
458 isl_pw_aff
*lhs
= create_pw_aff_from_tree (pbb
, gimple_cond_lhs (stmt
));
459 isl_pw_aff
*rhs
= create_pw_aff_from_tree (pbb
, gimple_cond_rhs (stmt
));
465 cond
= isl_pw_aff_lt_set (lhs
, rhs
);
469 cond
= isl_pw_aff_gt_set (lhs
, rhs
);
473 cond
= isl_pw_aff_le_set (lhs
, rhs
);
477 cond
= isl_pw_aff_ge_set (lhs
, rhs
);
481 cond
= isl_pw_aff_eq_set (lhs
, rhs
);
485 cond
= isl_pw_aff_ne_set (lhs
, rhs
);
492 cond
= isl_set_coalesce (cond
);
493 cond
= isl_set_set_tuple_id (cond
, isl_set_get_tuple_id (pbb
->domain
));
494 pbb
->domain
= isl_set_coalesce (isl_set_intersect (pbb
->domain
, cond
));
497 /* Add conditions to the domain of PBB. */
500 add_conditions_to_domain (poly_bb_p pbb
)
504 gimple_poly_bb_p gbb
= PBB_BLACK_BOX (pbb
);
506 if (GBB_CONDITIONS (gbb
).is_empty ())
509 FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb
), i
, stmt
)
510 switch (gimple_code (stmt
))
514 /* Don't constrain on anything else than INTEGER_TYPE. */
515 if (TREE_CODE (TREE_TYPE (gimple_cond_lhs (stmt
))) != INTEGER_TYPE
)
518 gcond
*cond_stmt
= as_a
<gcond
*> (stmt
);
519 enum tree_code code
= gimple_cond_code (cond_stmt
);
521 /* The conditions for ELSE-branches are inverted. */
522 if (!GBB_CONDITION_CASES (gbb
)[i
])
523 code
= invert_tree_comparison (code
, false);
525 add_condition_to_pbb (pbb
, cond_stmt
, code
);
535 /* Add constraints on the possible values of parameter P from the type
539 add_param_constraints (scop_p scop
, graphite_dim_t p
)
541 tree parameter
= scop
->scop_info
->params
[p
];
542 tree type
= TREE_TYPE (parameter
);
546 if (POINTER_TYPE_P (type
) || !TYPE_MIN_VALUE (type
))
547 lb
= lower_bound_in_type (type
, type
);
549 lb
= TYPE_MIN_VALUE (type
);
551 if (POINTER_TYPE_P (type
) || !TYPE_MAX_VALUE (type
))
552 ub
= upper_bound_in_type (type
, type
);
554 ub
= TYPE_MAX_VALUE (type
);
558 isl_space
*space
= isl_set_get_space (scop
->param_context
);
563 c
= isl_inequality_alloc (isl_local_space_from_space (space
));
565 tree_int_to_gmp (lb
, g
);
566 v
= isl_val_int_from_gmp (scop
->isl_context
, g
);
569 c
= isl_constraint_set_constant_val (c
, v
);
570 c
= isl_constraint_set_coefficient_si (c
, isl_dim_param
, p
, 1);
572 scop
->param_context
= isl_set_coalesce
573 (isl_set_add_constraint (scop
->param_context
, c
));
578 isl_space
*space
= isl_set_get_space (scop
->param_context
);
583 c
= isl_inequality_alloc (isl_local_space_from_space (space
));
586 tree_int_to_gmp (ub
, g
);
587 v
= isl_val_int_from_gmp (scop
->isl_context
, g
);
589 c
= isl_constraint_set_constant_val (c
, v
);
590 c
= isl_constraint_set_coefficient_si (c
, isl_dim_param
, p
, -1);
592 scop
->param_context
= isl_set_coalesce
593 (isl_set_add_constraint (scop
->param_context
, c
));
597 /* Add a constrain to the ACCESSES polyhedron for the alias set of
598 data reference DR. ACCESSP_NB_DIMS is the dimension of the
599 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
603 pdr_add_alias_set (isl_map
*acc
, dr_info
&dri
)
605 isl_constraint
*c
= isl_equality_alloc
606 (isl_local_space_from_space (isl_map_get_space (acc
)));
607 /* Positive numbers for all alias sets. */
608 c
= isl_constraint_set_constant_si (c
, -dri
.alias_set
);
609 c
= isl_constraint_set_coefficient_si (c
, isl_dim_out
, 0, 1);
611 return isl_map_add_constraint (acc
, c
);
614 /* Add a constrain to the ACCESSES polyhedron for the alias set of
615 data reference DR. ACCESSP_NB_DIMS is the dimension of the
616 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
620 add_scalar_version_numbers (isl_map
*acc
, tree var
)
622 isl_constraint
*c
= isl_equality_alloc
623 (isl_local_space_from_space (isl_map_get_space (acc
)));
624 int max_arrays
= PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP
);
625 /* Each scalar variables has a unique alias set number starting from
627 c
= isl_constraint_set_constant_si (c
, -max_arrays
- SSA_NAME_VERSION (var
));
628 c
= isl_constraint_set_coefficient_si (c
, isl_dim_out
, 0, 1);
630 return isl_map_add_constraint (acc
, c
);
633 /* Assign the affine expression INDEX to the output dimension POS of
634 MAP and return the result. */
637 set_index (isl_map
*map
, int pos
, isl_pw_aff
*index
)
640 int len
= isl_map_dim (map
, isl_dim_out
);
643 index_map
= isl_map_from_pw_aff (index
);
644 index_map
= isl_map_insert_dims (index_map
, isl_dim_out
, 0, pos
);
645 index_map
= isl_map_add_dims (index_map
, isl_dim_out
, len
- pos
- 1);
647 id
= isl_map_get_tuple_id (map
, isl_dim_out
);
648 index_map
= isl_map_set_tuple_id (index_map
, isl_dim_out
, id
);
649 id
= isl_map_get_tuple_id (map
, isl_dim_in
);
650 index_map
= isl_map_set_tuple_id (index_map
, isl_dim_in
, id
);
652 return isl_map_intersect (map
, index_map
);
655 /* Add to ACCESSES polyhedron equalities defining the access functions
656 to the memory. ACCESSP_NB_DIMS is the dimension of the ACCESSES
657 polyhedron, DOM_NB_DIMS is the dimension of the iteration domain.
658 PBB is the poly_bb_p that contains the data reference DR. */
661 pdr_add_memory_accesses (isl_map
*acc
, dr_info
&dri
)
663 data_reference_p dr
= dri
.dr
;
664 poly_bb_p pbb
= dri
.pbb
;
665 int i
, nb_subscripts
= DR_NUM_DIMENSIONS (dr
);
666 scop_p scop
= PBB_SCOP (pbb
);
668 for (i
= 0; i
< nb_subscripts
; i
++)
671 tree afn
= DR_ACCESS_FN (dr
, i
);
673 aff
= extract_affine (scop
, afn
,
674 isl_space_domain (isl_map_get_space (acc
)));
675 acc
= set_index (acc
, nb_subscripts
- i
, aff
);
678 return isl_map_coalesce (acc
);
681 /* Return true when the LOW and HIGH bounds of an array reference REF are valid
682 to extract constraints on accessed elements of the array. Returning false is
683 the conservative answer. */
686 bounds_are_valid (tree ref
, tree low
, tree high
)
691 if (!tree_fits_shwi_p (low
)
692 || !tree_fits_shwi_p (high
))
695 /* 1-element arrays at end of structures may extend over
696 their declared size. */
697 if (array_at_struct_end_p (ref
)
698 && operand_equal_p (low
, high
, 0))
701 /* Fortran has some arrays where high bound is -1 and low is 0. */
702 if (integer_onep (fold_build2 (LT_EXPR
, boolean_type_node
, high
, low
)))
708 /* Add constrains representing the size of the accessed data to the
709 ACCESSES polyhedron. ACCESSP_NB_DIMS is the dimension of the
710 ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
714 pdr_add_data_dimensions (isl_set
*subscript_sizes
, scop_p scop
,
717 tree ref
= DR_REF (dr
);
719 int nb_subscripts
= DR_NUM_DIMENSIONS (dr
);
720 for (int i
= nb_subscripts
- 1; i
>= 0; i
--, ref
= TREE_OPERAND (ref
, 0))
722 if (TREE_CODE (ref
) != ARRAY_REF
)
723 return subscript_sizes
;
725 tree low
= array_ref_low_bound (ref
);
726 tree high
= array_ref_up_bound (ref
);
728 if (!bounds_are_valid (ref
, low
, high
))
731 isl_space
*space
= isl_set_get_space (subscript_sizes
);
732 isl_pw_aff
*lb
= extract_affine_int (low
, isl_space_copy (space
));
733 isl_pw_aff
*ub
= extract_affine_int (high
, isl_space_copy (space
));
736 isl_set
*valid
= isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub
));
737 valid
= isl_set_project_out (valid
, isl_dim_set
, 0,
738 isl_set_dim (valid
, isl_dim_set
));
739 scop
->param_context
= isl_set_coalesce
740 (isl_set_intersect (scop
->param_context
, valid
));
743 = isl_aff_zero_on_domain (isl_local_space_from_space (space
));
744 aff
= isl_aff_add_coefficient_si (aff
, isl_dim_in
, i
+ 1, 1);
746 = isl_set_universe (isl_space_domain (isl_aff_get_space (aff
)));
747 isl_pw_aff
*index
= isl_pw_aff_alloc (univ
, aff
);
749 isl_id
*id
= isl_set_get_tuple_id (subscript_sizes
);
750 lb
= isl_pw_aff_set_tuple_id (lb
, isl_dim_in
, isl_id_copy (id
));
751 ub
= isl_pw_aff_set_tuple_id (ub
, isl_dim_in
, id
);
753 /* low <= sub_i <= high */
754 isl_set
*lbs
= isl_pw_aff_ge_set (isl_pw_aff_copy (index
), lb
);
755 isl_set
*ubs
= isl_pw_aff_le_set (index
, ub
);
756 subscript_sizes
= isl_set_intersect (subscript_sizes
, lbs
);
757 subscript_sizes
= isl_set_intersect (subscript_sizes
, ubs
);
760 return isl_set_coalesce (subscript_sizes
);
763 /* Build data accesses for DRI. */
766 build_poly_dr (dr_info
&dri
)
769 isl_set
*subscript_sizes
;
770 poly_bb_p pbb
= dri
.pbb
;
771 data_reference_p dr
= dri
.dr
;
772 scop_p scop
= PBB_SCOP (pbb
);
773 isl_id
*id
= isl_id_for_dr (scop
);
776 isl_space
*dc
= isl_set_get_space (pbb
->domain
);
777 int nb_out
= 1 + DR_NUM_DIMENSIONS (dr
);
778 isl_space
*space
= isl_space_add_dims (isl_space_from_domain (dc
),
779 isl_dim_out
, nb_out
);
781 acc
= isl_map_universe (space
);
782 acc
= isl_map_set_tuple_id (acc
, isl_dim_out
, isl_id_copy (id
));
785 acc
= pdr_add_alias_set (acc
, dri
);
786 acc
= pdr_add_memory_accesses (acc
, dri
);
789 int nb
= 1 + DR_NUM_DIMENSIONS (dr
);
790 isl_space
*space
= isl_space_set_alloc (scop
->isl_context
, 0, nb
);
792 space
= isl_space_set_tuple_id (space
, isl_dim_set
, id
);
793 subscript_sizes
= isl_set_nat_universe (space
);
794 subscript_sizes
= isl_set_fix_si (subscript_sizes
, isl_dim_set
, 0,
796 subscript_sizes
= pdr_add_data_dimensions (subscript_sizes
, scop
, dr
);
799 new_poly_dr (pbb
, DR_STMT (dr
), DR_IS_READ (dr
) ? PDR_READ
: PDR_WRITE
,
800 acc
, subscript_sizes
);
804 build_poly_sr_1 (poly_bb_p pbb
, gimple
*stmt
, tree var
, enum poly_dr_type kind
,
805 isl_map
*acc
, isl_set
*subscript_sizes
)
807 int max_arrays
= PARAM_VALUE (PARAM_GRAPHITE_MAX_ARRAYS_PER_SCOP
);
808 /* Each scalar variables has a unique alias set number starting from
810 subscript_sizes
= isl_set_fix_si (subscript_sizes
, isl_dim_set
, 0,
811 max_arrays
+ SSA_NAME_VERSION (var
));
813 new_poly_dr (pbb
, stmt
, kind
, add_scalar_version_numbers (acc
, var
),
817 /* Record all cross basic block scalar variables in PBB. */
820 build_poly_sr (poly_bb_p pbb
)
822 scop_p scop
= PBB_SCOP (pbb
);
823 gimple_poly_bb_p gbb
= PBB_BLACK_BOX (pbb
);
824 vec
<scalar_use
> &reads
= gbb
->read_scalar_refs
;
825 vec
<tree
> &writes
= gbb
->write_scalar_refs
;
827 isl_space
*dc
= isl_set_get_space (pbb
->domain
);
829 isl_space
*space
= isl_space_add_dims (isl_space_from_domain (dc
),
830 isl_dim_out
, nb_out
);
831 isl_id
*id
= isl_id_for_dr (scop
);
832 space
= isl_space_set_tuple_id (space
, isl_dim_set
, isl_id_copy (id
));
833 isl_map
*acc
= isl_map_universe (isl_space_copy (space
));
834 acc
= isl_map_set_tuple_id (acc
, isl_dim_out
, id
);
835 isl_set
*subscript_sizes
= isl_set_nat_universe (space
);
839 FOR_EACH_VEC_ELT (writes
, i
, var
)
840 build_poly_sr_1 (pbb
, SSA_NAME_DEF_STMT (var
), var
, PDR_WRITE
,
841 isl_map_copy (acc
), isl_set_copy (subscript_sizes
));
844 FOR_EACH_VEC_ELT (reads
, i
, use
)
845 build_poly_sr_1 (pbb
, use
->first
, use
->second
, PDR_READ
, isl_map_copy (acc
),
846 isl_set_copy (subscript_sizes
));
849 isl_set_free (subscript_sizes
);
852 /* Build data references in SCOP. */
855 build_scop_drs (scop_p scop
)
859 FOR_EACH_VEC_ELT (scop
->drs
, i
, dri
)
860 build_poly_dr (*dri
);
863 FOR_EACH_VEC_ELT (scop
->pbbs
, i
, pbb
)
867 /* Add to the iteration DOMAIN one extra dimension for LOOP->num. */
870 add_iter_domain_dimension (__isl_take isl_set
*domain
, loop_p loop
, scop_p scop
)
872 int loop_index
= isl_set_dim (domain
, isl_dim_set
);
873 domain
= isl_set_add_dims (domain
, isl_dim_set
, 1);
875 snprintf (name
, sizeof(name
), "i%d", loop
->num
);
876 isl_id
*label
= isl_id_alloc (scop
->isl_context
, name
, NULL
);
877 return isl_set_set_dim_id (domain
, isl_dim_set
, loop_index
, label
);
880 /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT. */
883 add_loop_constraints (scop_p scop
, __isl_take isl_set
*domain
, loop_p loop
,
888 const sese_l
®ion
= scop
->scop_info
->region
;
889 if (!loop_in_sese_p (loop
, region
))
892 /* Recursion all the way up to the context loop. */
893 domain
= add_loop_constraints (scop
, domain
, loop_outer (loop
), context
);
895 /* Then, build constraints over the loop in post-order: outer to inner. */
897 int loop_index
= isl_set_dim (domain
, isl_dim_set
);
899 fprintf (dump_file
, "[sese-to-poly] adding one extra dimension to the "
900 "domain for loop_%d.\n", loop
->num
);
901 domain
= add_iter_domain_dimension (domain
, loop
, scop
);
902 isl_space
*space
= isl_set_get_space (domain
);
905 isl_local_space
*ls
= isl_local_space_from_space (isl_space_copy (space
));
906 isl_constraint
*c
= isl_inequality_alloc (ls
);
907 c
= isl_constraint_set_coefficient_si (c
, isl_dim_set
, loop_index
, 1);
910 fprintf (dump_file
, "[sese-to-poly] adding constraint to the domain: ");
911 print_isl_constraint (dump_file
, c
);
913 domain
= isl_set_add_constraint (domain
, c
);
915 tree nb_iters
= number_of_latch_executions (loop
);
916 if (TREE_CODE (nb_iters
) == INTEGER_CST
)
918 /* loop_i <= cst_nb_iters */
919 isl_local_space
*ls
= isl_local_space_from_space (space
);
920 isl_constraint
*c
= isl_inequality_alloc (ls
);
921 c
= isl_constraint_set_coefficient_si (c
, isl_dim_set
, loop_index
, -1);
924 tree_int_to_gmp (nb_iters
, g
);
925 isl_val
*v
= isl_val_int_from_gmp (scop
->isl_context
, g
);
927 c
= isl_constraint_set_constant_val (c
, v
);
928 return isl_set_add_constraint (domain
, c
);
930 /* loop_i <= expr_nb_iters */
931 gcc_assert (!chrec_contains_undetermined (nb_iters
));
932 nb_iters
= scalar_evolution_in_region (region
, loop
, nb_iters
);
933 gcc_assert (!chrec_contains_undetermined (nb_iters
));
935 isl_pw_aff
*aff_nb_iters
= extract_affine (scop
, nb_iters
,
936 isl_space_copy (space
));
937 isl_set
*valid
= isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters
));
938 valid
= isl_set_project_out (valid
, isl_dim_set
, 0,
939 isl_set_dim (valid
, isl_dim_set
));
942 scop
->param_context
= isl_set_intersect (scop
->param_context
, valid
);
944 ls
= isl_local_space_from_space (isl_space_copy (space
));
945 isl_aff
*loop_i
= isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls
),
946 isl_dim_in
, loop_index
, 1);
947 isl_set
*le
= isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i
),
948 isl_pw_aff_copy (aff_nb_iters
));
951 fprintf (dump_file
, "[sese-to-poly] adding constraint to the domain: ");
952 print_isl_set (dump_file
, le
);
954 domain
= isl_set_intersect (domain
, le
);
957 if (!max_stmt_executions (loop
, &nit
))
959 isl_pw_aff_free (aff_nb_iters
);
960 isl_space_free (space
);
964 /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we
965 do not know whether the loop executes at least once. */
968 wi::to_mpz (nit
, g
, SIGNED
);
969 mpz_sub_ui (g
, g
, 1);
971 isl_pw_aff
*approx
= extract_affine_gmp (g
, isl_space_copy (space
));
972 isl_set
*x
= isl_pw_aff_ge_set (approx
, aff_nb_iters
);
973 x
= isl_set_project_out (x
, isl_dim_set
, 0,
974 isl_set_dim (x
, isl_dim_set
));
975 scop
->param_context
= isl_set_intersect (scop
->param_context
, x
);
977 ls
= isl_local_space_from_space (space
);
978 c
= isl_inequality_alloc (ls
);
979 c
= isl_constraint_set_coefficient_si (c
, isl_dim_set
, loop_index
, -1);
980 isl_val
*v
= isl_val_int_from_gmp (scop
->isl_context
, g
);
982 c
= isl_constraint_set_constant_val (c
, v
);
986 fprintf (dump_file
, "[sese-to-poly] adding constraint to the domain: ");
987 print_isl_constraint (dump_file
, c
);
990 return isl_set_add_constraint (domain
, c
);
993 /* Builds the original iteration domains for each pbb in the SCOP. */
996 build_iteration_domains (scop_p scop
, __isl_keep isl_set
*context
,
997 int index
, loop_p context_loop
)
999 loop_p current
= pbb_loop (scop
->pbbs
[index
]);
1000 isl_set
*domain
= isl_set_copy (context
);
1001 domain
= add_loop_constraints (scop
, domain
, current
, context_loop
);
1002 const sese_l
®ion
= scop
->scop_info
->region
;
1006 FOR_EACH_VEC_ELT_FROM (scop
->pbbs
, i
, pbb
, index
)
1008 loop_p loop
= pbb_loop (pbb
);
1009 if (current
== loop
)
1011 #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
1012 pbb
->iterators
= isl_set_copy (domain
);
1014 pbb
->domain
= isl_set_copy (domain
);
1015 pbb
->domain
= isl_set_set_tuple_id (pbb
->domain
,
1016 isl_id_for_pbb (scop
, pbb
));
1017 add_conditions_to_domain (pbb
);
1021 fprintf (dump_file
, "[sese-to-poly] set pbb_%d->domain: ",
1023 print_isl_set (dump_file
, domain
);
1028 while (loop_in_sese_p (loop
, region
)
1030 loop
= loop_outer (loop
);
1032 if (current
!= loop
)
1034 /* A statement in a different loop nest than CURRENT loop. */
1035 isl_set_free (domain
);
1039 /* A statement nested in the CURRENT loop. */
1040 i
= build_iteration_domains (scop
, domain
, i
, current
);
1044 isl_set_free (domain
);
1048 /* Assign dimension for each parameter in SCOP and add constraints for the
1052 build_scop_context (scop_p scop
)
1054 sese_info_p region
= scop
->scop_info
;
1055 unsigned nbp
= sese_nb_params (region
);
1056 isl_space
*space
= isl_space_set_alloc (scop
->isl_context
, nbp
, 0);
1060 FOR_EACH_VEC_ELT (region
->params
, i
, e
)
1061 space
= isl_space_set_dim_id (space
, isl_dim_param
, i
,
1062 isl_id_for_ssa_name (scop
, e
));
1064 scop
->param_context
= isl_set_universe (space
);
1067 for (p
= 0; p
< nbp
; p
++)
1068 add_param_constraints (scop
, p
);
1071 #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
1073 /* Return true when loop A is nested in loop B. */
1076 nested_in (loop_p a
, loop_p b
)
1078 return b
== find_common_loop (a
, b
);
1081 /* Return the loop at a specific SCOP->pbbs[*INDEX]. */
1083 loop_at (scop_p scop
, int *index
)
1085 return pbb_loop (scop
->pbbs
[*index
]);
1088 /* Return the index of any pbb belonging to loop or a subloop of A. */
1091 index_outermost_in_loop (loop_p a
, scop_p scop
)
1093 int i
, outermost
= -1;
1094 int last_depth
= -1;
1096 FOR_EACH_VEC_ELT (scop
->pbbs
, i
, pbb
)
1097 if (nested_in (pbb_loop (pbb
), a
)
1098 && (last_depth
== -1
1099 || last_depth
> (int) loop_depth (pbb_loop (pbb
))))
1102 last_depth
= loop_depth (pbb_loop (pbb
));
1107 /* Return the index of any pbb belonging to loop or a subloop of A. */
1110 index_pbb_in_loop (loop_p a
, scop_p scop
)
1114 FOR_EACH_VEC_ELT (scop
->pbbs
, i
, pbb
)
1115 if (pbb_loop (pbb
) == a
)
1121 outermost_pbb_in (loop_p loop
, scop_p scop
)
1123 int x
= index_pbb_in_loop (loop
, scop
);
1125 x
= index_outermost_in_loop (loop
, scop
);
1126 return scop
->pbbs
[x
];
1129 static isl_schedule
*
1130 add_in_sequence (__isl_take isl_schedule
*a
, __isl_take isl_schedule
*b
)
1132 gcc_assert (a
|| b
);
1140 return isl_schedule_sequence (a
, b
);
1143 struct map_to_dimension_data
{
1145 isl_union_pw_multi_aff
*res
;
1148 /* Create a function that maps the elements of SET to its N-th dimension and add
1152 add_outer_projection (__isl_take isl_set
*set
, void *user
)
1154 struct map_to_dimension_data
*data
= (struct map_to_dimension_data
*) user
;
1155 int dim
= isl_set_dim (set
, isl_dim_set
);
1156 isl_space
*space
= isl_set_get_space (set
);
1158 gcc_assert (dim
>= data
->n
);
1159 isl_pw_multi_aff
*pma
1160 = isl_pw_multi_aff_project_out_map (space
, isl_dim_set
, data
->n
,
1162 data
->res
= isl_union_pw_multi_aff_add_pw_multi_aff (data
->res
, pma
);
1168 /* Return SET in which all inner dimensions above N are removed. */
1170 static isl_multi_union_pw_aff
*
1171 outer_projection_mupa (__isl_take isl_union_set
*set
, int n
)
1173 gcc_assert (n
>= 0);
1175 gcc_assert (!isl_union_set_is_empty (set
));
1177 isl_space
*space
= isl_union_set_get_space (set
);
1178 isl_union_pw_multi_aff
*pwaff
= isl_union_pw_multi_aff_empty (space
);
1180 struct map_to_dimension_data data
= {n
, pwaff
};
1182 if (isl_union_set_foreach_set (set
, &add_outer_projection
, &data
) < 0)
1183 data
.res
= isl_union_pw_multi_aff_free (data
.res
);
1185 isl_union_set_free (set
);
1186 return isl_multi_union_pw_aff_from_union_pw_multi_aff (data
.res
);
1189 /* Embed SCHEDULE in the constraints of the LOOP domain. */
1191 static isl_schedule
*
1192 add_loop_schedule (__isl_take isl_schedule
*schedule
, loop_p loop
,
1195 poly_bb_p pbb
= outermost_pbb_in (loop
, scop
);
1196 isl_set
*iterators
= pbb
->iterators
;
1198 int empty
= isl_set_is_empty (iterators
);
1199 if (empty
< 0 || empty
)
1200 return empty
< 0 ? isl_schedule_free (schedule
) : schedule
;
1202 isl_space
*space
= isl_set_get_space (iterators
);
1203 int loop_index
= isl_space_dim (space
, isl_dim_set
) - 1;
1205 loop_p ploop
= pbb_loop (pbb
);
1206 while (loop
!= ploop
)
1209 ploop
= loop_outer (ploop
);
1212 isl_local_space
*ls
= isl_local_space_from_space (space
);
1213 isl_aff
*aff
= isl_aff_var_on_domain (ls
, isl_dim_set
, loop_index
);
1214 isl_multi_aff
*prefix
= isl_multi_aff_from_aff (aff
);
1216 snprintf (name
, sizeof(name
), "L_%d", loop
->num
);
1217 isl_id
*label
= isl_id_alloc (isl_schedule_get_ctx (schedule
),
1219 prefix
= isl_multi_aff_set_tuple_id (prefix
, isl_dim_out
, label
);
1221 int n
= isl_multi_aff_dim (prefix
, isl_dim_in
);
1222 isl_union_set
*domain
= isl_schedule_get_domain (schedule
);
1223 isl_multi_union_pw_aff
*mupa
= outer_projection_mupa (domain
, n
);
1224 mupa
= isl_multi_union_pw_aff_apply_multi_aff (mupa
, prefix
);
1225 return isl_schedule_insert_partial_schedule (schedule
, mupa
);
1228 /* Build schedule for the pbb at INDEX. */
1230 static isl_schedule
*
1231 build_schedule_pbb (scop_p scop
, int *index
)
1233 poly_bb_p pbb
= scop
->pbbs
[*index
];
1235 isl_set
*domain
= isl_set_copy (pbb
->domain
);
1236 isl_union_set
*ud
= isl_union_set_from_set (domain
);
1237 return isl_schedule_from_domain (ud
);
1240 static isl_schedule
*build_schedule_loop_nest (scop_p
, int *, loop_p
);
1242 /* Build the schedule of the loop containing the SCOP pbb at INDEX. */
1244 static isl_schedule
*
1245 build_schedule_loop (scop_p scop
, int *index
)
1247 int max
= scop
->pbbs
.length ();
1248 gcc_assert (*index
< max
);
1249 loop_p loop
= loop_at (scop
, index
);
1251 isl_schedule
*s
= NULL
;
1252 while (nested_in (loop_at (scop
, index
), loop
))
1254 if (loop
== loop_at (scop
, index
))
1255 s
= add_in_sequence (s
, build_schedule_pbb (scop
, index
));
1257 s
= add_in_sequence (s
, build_schedule_loop_nest (scop
, index
, loop
));
1263 return add_loop_schedule (s
, loop
, scop
);
1266 /* S is the schedule of the loop LOOP. Embed the schedule S in all outer loops.
1267 When CONTEXT_LOOP is null, embed the schedule in all loops contained in the
1268 SCOP surrounding LOOP. When CONTEXT_LOOP is non null, only embed S in the
1269 maximal loop nest contained within CONTEXT_LOOP. */
1271 static isl_schedule
*
1272 embed_in_surrounding_loops (__isl_take isl_schedule
*s
, scop_p scop
,
1273 loop_p loop
, int *index
, loop_p context_loop
)
1275 loop_p outer
= loop_outer (loop
);
1276 sese_l region
= scop
->scop_info
->region
;
1277 if (context_loop
== outer
1278 || !loop_in_sese_p (outer
, region
))
1281 int max
= scop
->pbbs
.length ();
1283 || (context_loop
&& !nested_in (loop_at (scop
, index
), context_loop
))
1285 && !loop_in_sese_p (find_common_loop (outer
, loop_at (scop
, index
)),
1287 return embed_in_surrounding_loops (add_loop_schedule (s
, outer
, scop
),
1288 scop
, outer
, index
, context_loop
);
1291 while ((a_pbb
= (outer
== loop_at (scop
, index
)))
1292 || nested_in (loop_at (scop
, index
), outer
))
1295 s
= add_in_sequence (s
, build_schedule_pbb (scop
, index
));
1297 s
= add_in_sequence (s
, build_schedule_loop (scop
, index
));
1303 /* We reached the end of the OUTER loop: embed S in OUTER. */
1304 return embed_in_surrounding_loops (add_loop_schedule (s
, outer
, scop
), scop
,
1305 outer
, index
, context_loop
);
1308 /* Build schedule for the full loop nest containing the pbb at INDEX. When
1309 CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP
1310 surrounding the pbb. When CONTEXT_LOOP is non null, only build the maximal loop
1311 nest contained within CONTEXT_LOOP. */
1313 static isl_schedule
*
1314 build_schedule_loop_nest (scop_p scop
, int *index
, loop_p context_loop
)
1316 gcc_assert (*index
!= (int) scop
->pbbs
.length ());
1318 loop_p loop
= loop_at (scop
, index
);
1319 isl_schedule
*s
= build_schedule_loop (scop
, index
);
1320 return embed_in_surrounding_loops (s
, scop
, loop
, index
, context_loop
);
1323 /* Build the schedule of the SCOP. */
1326 build_original_schedule (scop_p scop
)
1329 int n
= scop
->pbbs
.length ();
1332 poly_bb_p pbb
= scop
->pbbs
[i
];
1333 isl_schedule
*s
= NULL
;
1334 if (!loop_in_sese_p (pbb_loop (pbb
), scop
->scop_info
->region
))
1335 s
= build_schedule_pbb (scop
, &i
);
1337 s
= build_schedule_loop_nest (scop
, &i
, NULL
);
1339 scop
->original_schedule
= add_in_sequence (scop
->original_schedule
, s
);
1344 fprintf (dump_file
, "[sese-to-poly] original schedule:\n");
1345 print_isl_schedule (dump_file
, scop
->original_schedule
);
1347 if (!scop
->original_schedule
)
1354 /* Builds the polyhedral representation for a SESE region. */
1357 build_poly_scop (scop_p scop
)
1359 build_scop_context (scop
);
1362 unsigned n
= scop
->pbbs
.length ();
1364 i
= build_iteration_domains (scop
, scop
->param_context
, i
, NULL
);
1366 build_scop_drs (scop
);
1367 #ifdef HAVE_ISL_OPTIONS_SET_SCHEDULE_SERIALIZE_SCCS
1368 build_original_schedule (scop
);
1370 build_scop_scattering (scop
);
1374 #endif /* HAVE_isl */