aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-data-ref.c
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2021-09-13 19:49:49 +0200
committerThomas Koenig <tkoenig@gcc.gnu.org>2021-09-13 19:49:49 +0200
commitb18a97e5dd0935e1c4a626c230f21457d0aad3d5 (patch)
treec1818f41af6fe780deafb6cd6a183f32085fe654 /gcc/tree-data-ref.c
parente76a53644c9d70e998c0d050e9a456af388c6b61 (diff)
downloadgcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.zip
gcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.tar.gz
gcc-b18a97e5dd0935e1c4a626c230f21457d0aad3d5.tar.bz2
Merged current trunk to branch.
Diffstat (limited to 'gcc/tree-data-ref.c')
-rw-r--r--gcc/tree-data-ref.c496
1 files changed, 262 insertions, 234 deletions
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index 926553b..e061baa 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -1,5 +1,5 @@
/* Data references and dependences detectors.
- Copyright (C) 2003-2020 Free Software Foundation, Inc.
+ Copyright (C) 2003-2021 Free Software Foundation, Inc.
Contributed by Sebastian Pop <pop@cri.ensmp.fr>
This file is part of GCC.
@@ -97,8 +97,8 @@ along with GCC; see the file COPYING3. If not see
#include "tree-eh.h"
#include "ssa.h"
#include "internal-fn.h"
-#include "range-op.h"
#include "vr-values.h"
+#include "range-op.h"
static struct datadep_stats
{
@@ -143,7 +143,7 @@ tree_fold_divides_p (const_tree a, const_tree b)
/* Returns true iff A divides B. */
static inline bool
-int_divides_p (int a, int b)
+int_divides_p (lambda_int a, lambda_int b)
{
return ((b % a) == 0);
}
@@ -170,10 +170,7 @@ ref_contains_union_access_p (tree ref)
static void
dump_data_references (FILE *file, vec<data_reference_p> datarefs)
{
- unsigned int i;
- struct data_reference *dr;
-
- FOR_EACH_VEC_ELT (datarefs, i, dr)
+ for (data_reference *dr : datarefs)
dump_data_reference (file, dr);
}
@@ -378,10 +375,7 @@ DEBUG_FUNCTION void
print_dir_vectors (FILE *outf, vec<lambda_vector> dir_vects,
int length)
{
- unsigned j;
- lambda_vector v;
-
- FOR_EACH_VEC_ELT (dir_vects, j, v)
+ for (lambda_vector v : dir_vects)
print_direction_vector (outf, v, length);
}
@@ -403,18 +397,14 @@ DEBUG_FUNCTION void
print_dist_vectors (FILE *outf, vec<lambda_vector> dist_vects,
int length)
{
- unsigned j;
- lambda_vector v;
-
- FOR_EACH_VEC_ELT (dist_vects, j, v)
+ for (lambda_vector v : dist_vects)
print_lambda_vector (outf, v, length);
}
/* Dump function for a DATA_DEPENDENCE_RELATION structure. */
DEBUG_FUNCTION void
-dump_data_dependence_relation (FILE *outf,
- struct data_dependence_relation *ddr)
+dump_data_dependence_relation (FILE *outf, const data_dependence_relation *ddr)
{
struct data_reference *dra, *drb;
@@ -488,7 +478,7 @@ dump_data_dependence_relation (FILE *outf,
/* Debug version. */
DEBUG_FUNCTION void
-debug_data_dependence_relation (struct data_dependence_relation *ddr)
+debug_data_dependence_relation (const struct data_dependence_relation *ddr)
{
dump_data_dependence_relation (stderr, ddr);
}
@@ -496,13 +486,9 @@ debug_data_dependence_relation (struct data_dependence_relation *ddr)
/* Dump into FILE all the dependence relations from DDRS. */
DEBUG_FUNCTION void
-dump_data_dependence_relations (FILE *file,
- vec<ddr_p> ddrs)
+dump_data_dependence_relations (FILE *file, const vec<ddr_p> &ddrs)
{
- unsigned int i;
- struct data_dependence_relation *ddr;
-
- FOR_EACH_VEC_ELT (ddrs, i, ddr)
+ for (auto ddr : ddrs)
dump_data_dependence_relation (file, ddr);
}
@@ -538,21 +524,17 @@ debug_data_dependence_relations (vec<ddr_p> ddrs)
DEBUG_FUNCTION void
dump_dist_dir_vectors (FILE *file, vec<ddr_p> ddrs)
{
- unsigned int i, j;
- struct data_dependence_relation *ddr;
- lambda_vector v;
-
- FOR_EACH_VEC_ELT (ddrs, i, ddr)
+ for (data_dependence_relation *ddr : ddrs)
if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE && DDR_AFFINE_P (ddr))
{
- FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), j, v)
+ for (lambda_vector v : DDR_DIST_VECTS (ddr))
{
fprintf (file, "DISTANCE_V (");
print_lambda_vector (file, v, DDR_NB_LOOPS (ddr));
fprintf (file, ")\n");
}
- FOR_EACH_VEC_ELT (DDR_DIR_VECTS (ddr), j, v)
+ for (lambda_vector v : DDR_DIR_VECTS (ddr))
{
fprintf (file, "DIRECTION_V (");
print_direction_vector (file, v, DDR_NB_LOOPS (ddr));
@@ -568,10 +550,7 @@ dump_dist_dir_vectors (FILE *file, vec<ddr_p> ddrs)
DEBUG_FUNCTION void
dump_ddrs (FILE *file, vec<ddr_p> ddrs)
{
- unsigned int i;
- struct data_dependence_relation *ddr;
-
- FOR_EACH_VEC_ELT (ddrs, i, ddr)
+ for (data_dependence_relation *ddr : ddrs)
dump_data_dependence_relation (file, ddr);
fprintf (file, "\n\n");
@@ -1035,14 +1014,23 @@ split_constant_offset (tree exp, tree *var, tree *off, value_range *exp_range,
*exp_range = type;
if (code == SSA_NAME)
{
- wide_int var_min, var_max;
- value_range_kind vr_kind = get_range_info (exp, &var_min, &var_max);
+ value_range vr;
+ get_range_query (cfun)->range_of_expr (vr, exp);
+ if (vr.undefined_p ())
+ vr.set_varying (TREE_TYPE (exp));
+ wide_int var_min = wi::to_wide (vr.min ());
+ wide_int var_max = wi::to_wide (vr.max ());
+ value_range_kind vr_kind = vr.kind ();
wide_int var_nonzero = get_nonzero_bits (exp);
vr_kind = intersect_range_with_nonzero_bits (vr_kind,
&var_min, &var_max,
var_nonzero,
TYPE_SIGN (type));
- if (vr_kind == VR_RANGE)
+ /* This check for VR_VARYING is here because the old code
+ using get_range_info would return VR_RANGE for the entire
+ domain, instead of VR_VARYING. The new code normalizes
+ full-domain ranges to VR_VARYING. */
+ if (vr_kind == VR_RANGE || vr_kind == VR_VARYING)
*exp_range = value_range (type, var_min, var_max);
}
}
@@ -1060,12 +1048,12 @@ split_constant_offset (tree exp, tree *var, tree *off, value_range *exp_range,
if (INTEGRAL_TYPE_P (type))
*var = fold_convert (sizetype, *var);
*off = ssize_int (0);
- if (exp_range && code != SSA_NAME)
- {
- wide_int var_min, var_max;
- if (determine_value_range (exp, &var_min, &var_max) == VR_RANGE)
- *exp_range = value_range (type, var_min, var_max);
- }
+
+ value_range r;
+ if (exp_range && code != SSA_NAME
+ && get_range_query (cfun)->range_of_expr (r, exp)
+ && !r.undefined_p ())
+ *exp_range = r;
}
/* Expresses EXP as VAR + OFF, where OFF is a constant. VAR has the same
@@ -1291,6 +1279,23 @@ access_fn_component_p (tree op)
}
}
+/* Returns whether BASE can have a access_fn_component_p with BASE
+ as base. */
+
+static bool
+base_supports_access_fn_components_p (tree base)
+{
+ switch (TREE_CODE (TREE_TYPE (base)))
+ {
+ case COMPLEX_TYPE:
+ case ARRAY_TYPE:
+ case RECORD_TYPE:
+ return true;
+ default:
+ return false;
+ }
+}
+
/* Determines the base object and the list of indices of memory reference
DR, analyzed in LOOP and instantiated before NEST. */
@@ -2130,8 +2135,8 @@ create_intersect_range_checks_index (class loop *loop, tree *cond_expr,
bool waw_or_war_p = (alias_pair.flags & ~(DR_ALIAS_WAR | DR_ALIAS_WAW)) == 0;
- unsigned int i;
- for (i = 0; i < DR_NUM_DIMENSIONS (dr_a.dr); i++)
+ int found = -1;
+ for (unsigned int i = 0; i < DR_NUM_DIMENSIONS (dr_a.dr); i++)
{
tree access1 = DR_ACCESS_FN (dr_a.dr, i);
tree access2 = DR_ACCESS_FN (dr_b.dr, i);
@@ -2147,155 +2152,166 @@ create_intersect_range_checks_index (class loop *loop, tree *cond_expr,
return false;
}
- /* The two indices must have the same step. */
- if (!operand_equal_p (CHREC_RIGHT (access1), CHREC_RIGHT (access2), 0))
+ if (found >= 0)
return false;
+ found = i;
+ }
- tree idx_step = CHREC_RIGHT (access1);
- /* Index must have const step, otherwise DR_STEP won't be constant. */
- gcc_assert (TREE_CODE (idx_step) == INTEGER_CST);
- /* Index must evaluate in the same direction as DR. */
- gcc_assert (!neg_step || tree_int_cst_sign_bit (idx_step) == 1);
+ /* Ought not to happen in practice, since if all accesses are equal then the
+ alias should be decidable at compile time. */
+ if (found < 0)
+ return false;
- tree min1 = CHREC_LEFT (access1);
- tree min2 = CHREC_LEFT (access2);
- if (!types_compatible_p (TREE_TYPE (min1), TREE_TYPE (min2)))
- return false;
+ /* The two indices must have the same step. */
+ tree access1 = DR_ACCESS_FN (dr_a.dr, found);
+ tree access2 = DR_ACCESS_FN (dr_b.dr, found);
+ if (!operand_equal_p (CHREC_RIGHT (access1), CHREC_RIGHT (access2), 0))
+ return false;
- /* Ideally, alias can be checked against loop's control IV, but we
- need to prove linear mapping between control IV and reference
- index. Although that should be true, we check against (array)
- index of data reference. Like segment length, index length is
- linear function of the number of iterations with index_step as
- the coefficient, i.e, niter_len * idx_step. */
- offset_int abs_idx_step = offset_int::from (wi::to_wide (idx_step),
- SIGNED);
- if (neg_step)
- abs_idx_step = -abs_idx_step;
- poly_offset_int idx_len1 = abs_idx_step * niter_len1;
- poly_offset_int idx_len2 = abs_idx_step * niter_len2;
- poly_offset_int idx_access1 = abs_idx_step * niter_access1;
- poly_offset_int idx_access2 = abs_idx_step * niter_access2;
+ tree idx_step = CHREC_RIGHT (access1);
+ /* Index must have const step, otherwise DR_STEP won't be constant. */
+ gcc_assert (TREE_CODE (idx_step) == INTEGER_CST);
+ /* Index must evaluate in the same direction as DR. */
+ gcc_assert (!neg_step || tree_int_cst_sign_bit (idx_step) == 1);
- gcc_assert (known_ge (idx_len1, 0)
- && known_ge (idx_len2, 0)
- && known_ge (idx_access1, 0)
- && known_ge (idx_access2, 0));
+ tree min1 = CHREC_LEFT (access1);
+ tree min2 = CHREC_LEFT (access2);
+ if (!types_compatible_p (TREE_TYPE (min1), TREE_TYPE (min2)))
+ return false;
- /* Each access has the following pattern, with lengths measured
- in units of INDEX:
+ /* Ideally, alias can be checked against loop's control IV, but we
+ need to prove linear mapping between control IV and reference
+ index. Although that should be true, we check against (array)
+ index of data reference. Like segment length, index length is
+ linear function of the number of iterations with index_step as
+ the coefficient, i.e, niter_len * idx_step. */
+ offset_int abs_idx_step = offset_int::from (wi::to_wide (idx_step),
+ SIGNED);
+ if (neg_step)
+ abs_idx_step = -abs_idx_step;
+ poly_offset_int idx_len1 = abs_idx_step * niter_len1;
+ poly_offset_int idx_len2 = abs_idx_step * niter_len2;
+ poly_offset_int idx_access1 = abs_idx_step * niter_access1;
+ poly_offset_int idx_access2 = abs_idx_step * niter_access2;
- <-- idx_len -->
- <--- A: -ve step --->
- +-----+-------+-----+-------+-----+
- | n-1 | ..... | 0 | ..... | n-1 |
- +-----+-------+-----+-------+-----+
- <--- B: +ve step --->
- <-- idx_len -->
- |
- min
+ gcc_assert (known_ge (idx_len1, 0)
+ && known_ge (idx_len2, 0)
+ && known_ge (idx_access1, 0)
+ && known_ge (idx_access2, 0));
- where "n" is the number of scalar iterations covered by the segment
- and where each access spans idx_access units.
+ /* Each access has the following pattern, with lengths measured
+ in units of INDEX:
- A is the range of bytes accessed when the step is negative,
- B is the range when the step is positive.
+ <-- idx_len -->
+ <--- A: -ve step --->
+ +-----+-------+-----+-------+-----+
+ | n-1 | ..... | 0 | ..... | n-1 |
+ +-----+-------+-----+-------+-----+
+ <--- B: +ve step --->
+ <-- idx_len -->
+ |
+ min
- When checking for general overlap, we need to test whether
- the range:
+ where "n" is the number of scalar iterations covered by the segment
+ and where each access spans idx_access units.
- [min1 + low_offset1, min2 + high_offset1 + idx_access1 - 1]
+ A is the range of bytes accessed when the step is negative,
+ B is the range when the step is positive.
- overlaps:
+ When checking for general overlap, we need to test whether
+ the range:
- [min2 + low_offset2, min2 + high_offset2 + idx_access2 - 1]
+ [min1 + low_offset1, min1 + high_offset1 + idx_access1 - 1]
- where:
+ overlaps:
- low_offsetN = +ve step ? 0 : -idx_lenN;
- high_offsetN = +ve step ? idx_lenN : 0;
+ [min2 + low_offset2, min2 + high_offset2 + idx_access2 - 1]
- This is equivalent to testing whether:
+ where:
- min1 + low_offset1 <= min2 + high_offset2 + idx_access2 - 1
- && min2 + low_offset2 <= min1 + high_offset1 + idx_access1 - 1
+ low_offsetN = +ve step ? 0 : -idx_lenN;
+ high_offsetN = +ve step ? idx_lenN : 0;
- Converting this into a single test, there is an overlap if:
+ This is equivalent to testing whether:
- 0 <= min2 - min1 + bias <= limit
+ min1 + low_offset1 <= min2 + high_offset2 + idx_access2 - 1
+ && min2 + low_offset2 <= min1 + high_offset1 + idx_access1 - 1
- where bias = high_offset2 + idx_access2 - 1 - low_offset1
- limit = (high_offset1 - low_offset1 + idx_access1 - 1)
- + (high_offset2 - low_offset2 + idx_access2 - 1)
- i.e. limit = idx_len1 + idx_access1 - 1 + idx_len2 + idx_access2 - 1
+ Converting this into a single test, there is an overlap if:
- Combining the tests requires limit to be computable in an unsigned
- form of the index type; if it isn't, we fall back to the usual
- pointer-based checks.
+ 0 <= min2 - min1 + bias <= limit
- We can do better if DR_B is a write and if DR_A and DR_B are
- well-ordered in both the original and the new code (see the
- comment above the DR_ALIAS_* flags for details). In this case
- we know that for each i in [0, n-1], the write performed by
- access i of DR_B occurs after access numbers j<=i of DR_A in
- both the original and the new code. Any write or anti
- dependencies wrt those DR_A accesses are therefore maintained.
+ where bias = high_offset2 + idx_access2 - 1 - low_offset1
+ limit = (high_offset1 - low_offset1 + idx_access1 - 1)
+ + (high_offset2 - low_offset2 + idx_access2 - 1)
+ i.e. limit = idx_len1 + idx_access1 - 1 + idx_len2 + idx_access2 - 1
- We just need to make sure that each individual write in DR_B does not
- overlap any higher-indexed access in DR_A; such DR_A accesses happen
- after the DR_B access in the original code but happen before it in
- the new code.
+ Combining the tests requires limit to be computable in an unsigned
+ form of the index type; if it isn't, we fall back to the usual
+ pointer-based checks.
- We know the steps for both accesses are equal, so by induction, we
- just need to test whether the first write of DR_B overlaps a later
- access of DR_A. In other words, we need to move min1 along by
- one iteration:
+ We can do better if DR_B is a write and if DR_A and DR_B are
+ well-ordered in both the original and the new code (see the
+ comment above the DR_ALIAS_* flags for details). In this case
+ we know that for each i in [0, n-1], the write performed by
+ access i of DR_B occurs after access numbers j<=i of DR_A in
+ both the original and the new code. Any write or anti
+ dependencies wrt those DR_A accesses are therefore maintained.
- min1' = min1 + idx_step
+ We just need to make sure that each individual write in DR_B does not
+ overlap any higher-indexed access in DR_A; such DR_A accesses happen
+ after the DR_B access in the original code but happen before it in
+ the new code.
- and use the ranges:
+ We know the steps for both accesses are equal, so by induction, we
+ just need to test whether the first write of DR_B overlaps a later
+ access of DR_A. In other words, we need to move min1 along by
+ one iteration:
- [min1' + low_offset1', min1' + high_offset1' + idx_access1 - 1]
+ min1' = min1 + idx_step
- and:
+ and use the ranges:
- [min2, min2 + idx_access2 - 1]
+ [min1' + low_offset1', min1' + high_offset1' + idx_access1 - 1]
- where:
+ and:
- low_offset1' = +ve step ? 0 : -(idx_len1 - |idx_step|)
- high_offset1' = +ve_step ? idx_len1 - |idx_step| : 0. */
- if (waw_or_war_p)
- idx_len1 -= abs_idx_step;
+ [min2, min2 + idx_access2 - 1]
- poly_offset_int limit = idx_len1 + idx_access1 - 1 + idx_access2 - 1;
- if (!waw_or_war_p)
- limit += idx_len2;
+ where:
- tree utype = unsigned_type_for (TREE_TYPE (min1));
- if (!wi::fits_to_tree_p (limit, utype))
- return false;
+ low_offset1' = +ve step ? 0 : -(idx_len1 - |idx_step|)
+ high_offset1' = +ve_step ? idx_len1 - |idx_step| : 0. */
+ if (waw_or_war_p)
+ idx_len1 -= abs_idx_step;
- poly_offset_int low_offset1 = neg_step ? -idx_len1 : 0;
- poly_offset_int high_offset2 = neg_step || waw_or_war_p ? 0 : idx_len2;
- poly_offset_int bias = high_offset2 + idx_access2 - 1 - low_offset1;
- /* Equivalent to adding IDX_STEP to MIN1. */
- if (waw_or_war_p)
- bias -= wi::to_offset (idx_step);
-
- tree subject = fold_build2 (MINUS_EXPR, utype,
- fold_convert (utype, min2),
- fold_convert (utype, min1));
- subject = fold_build2 (PLUS_EXPR, utype, subject,
- wide_int_to_tree (utype, bias));
- tree part_cond_expr = fold_build2 (GT_EXPR, boolean_type_node, subject,
- wide_int_to_tree (utype, limit));
- if (*cond_expr)
- *cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
- *cond_expr, part_cond_expr);
- else
- *cond_expr = part_cond_expr;
- }
+ poly_offset_int limit = idx_len1 + idx_access1 - 1 + idx_access2 - 1;
+ if (!waw_or_war_p)
+ limit += idx_len2;
+
+ tree utype = unsigned_type_for (TREE_TYPE (min1));
+ if (!wi::fits_to_tree_p (limit, utype))
+ return false;
+
+ poly_offset_int low_offset1 = neg_step ? -idx_len1 : 0;
+ poly_offset_int high_offset2 = neg_step || waw_or_war_p ? 0 : idx_len2;
+ poly_offset_int bias = high_offset2 + idx_access2 - 1 - low_offset1;
+ /* Equivalent to adding IDX_STEP to MIN1. */
+ if (waw_or_war_p)
+ bias -= wi::to_offset (idx_step);
+
+ tree subject = fold_build2 (MINUS_EXPR, utype,
+ fold_convert (utype, min2),
+ fold_convert (utype, min1));
+ subject = fold_build2 (PLUS_EXPR, utype, subject,
+ wide_int_to_tree (utype, bias));
+ tree part_cond_expr = fold_build2 (GT_EXPR, boolean_type_node, subject,
+ wide_int_to_tree (utype, limit));
+ if (*cond_expr)
+ *cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+ *cond_expr, part_cond_expr);
+ else
+ *cond_expr = part_cond_expr;
if (dump_enabled_p ())
{
if (waw_or_war_p)
@@ -2625,25 +2641,23 @@ create_intersect_range_checks (class loop *loop, tree *cond_expr,
void
create_runtime_alias_checks (class loop *loop,
- vec<dr_with_seg_len_pair_t> *alias_pairs,
+ const vec<dr_with_seg_len_pair_t> *alias_pairs,
tree * cond_expr)
{
tree part_cond_expr;
fold_defer_overflow_warnings ();
- dr_with_seg_len_pair_t *alias_pair;
- unsigned int i;
- FOR_EACH_VEC_ELT (*alias_pairs, i, alias_pair)
+ for (const dr_with_seg_len_pair_t &alias_pair : alias_pairs)
{
- gcc_assert (alias_pair->flags);
+ gcc_assert (alias_pair.flags);
if (dump_enabled_p ())
dump_printf (MSG_NOTE,
"create runtime check for data references %T and %T\n",
- DR_REF (alias_pair->first.dr),
- DR_REF (alias_pair->second.dr));
+ DR_REF (alias_pair.first.dr),
+ DR_REF (alias_pair.second.dr));
/* Create condition expression for each pair data references. */
- create_intersect_range_checks (loop, &part_cond_expr, *alias_pair);
+ create_intersect_range_checks (loop, &part_cond_expr, alias_pair);
if (*cond_expr)
*cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
*cond_expr, part_cond_expr);
@@ -3272,8 +3286,13 @@ initialize_data_dependence_relation (struct data_reference *a,
&& full_seq.start_b + full_seq.length == num_dimensions_b
&& DR_UNCONSTRAINED_BASE (a) == DR_UNCONSTRAINED_BASE (b)
&& operand_equal_p (base_a, base_b, OEP_ADDRESS_OF)
- && types_compatible_p (TREE_TYPE (base_a),
- TREE_TYPE (base_b))
+ && (types_compatible_p (TREE_TYPE (base_a),
+ TREE_TYPE (base_b))
+ || (!base_supports_access_fn_components_p (base_a)
+ && !base_supports_access_fn_components_p (base_b)
+ && operand_equal_p
+ (TYPE_SIZE (TREE_TYPE (base_a)),
+ TYPE_SIZE (TREE_TYPE (base_b)), 0)))
&& (!loop_nest.exists ()
|| (object_address_invariant_in_loop_p
(loop_nest[0], base_a))));
@@ -3394,10 +3413,7 @@ free_conflict_function (conflict_function *f)
static void
free_subscripts (vec<subscript_p> subscripts)
{
- unsigned i;
- subscript_p s;
-
- FOR_EACH_VEC_ELT (subscripts, i, s)
+ for (subscript_p s : subscripts)
{
free_conflict_function (s->conflicting_iterations_in_a);
free_conflict_function (s->conflicting_iterations_in_b);
@@ -3902,9 +3918,14 @@ initialize_matrix_A (lambda_matrix A, tree chrec, unsigned index, int mult)
switch (TREE_CODE (chrec))
{
case POLYNOMIAL_CHREC:
+ HOST_WIDE_INT chrec_right;
if (!cst_and_fits_in_hwi (CHREC_RIGHT (chrec)))
return chrec_dont_know;
- A[index][0] = mult * int_cst_value (CHREC_RIGHT (chrec));
+ chrec_right = int_cst_value (CHREC_RIGHT (chrec));
+ /* We want to be able to negate without overflow. */
+ if (chrec_right == HOST_WIDE_INT_MIN)
+ return chrec_dont_know;
+ A[index][0] = mult * chrec_right;
return initialize_matrix_A (A, CHREC_LEFT (chrec), index + 1, mult);
case PLUS_EXPR:
@@ -4171,17 +4192,28 @@ lambda_vector_first_nz (lambda_vector vec1, int n, int start)
/* Add a multiple of row R1 of matrix MAT with N columns to row R2:
R2 = R2 + CONST1 * R1. */
-static void
+static bool
lambda_matrix_row_add (lambda_matrix mat, int n, int r1, int r2,
lambda_int const1)
{
int i;
if (const1 == 0)
- return;
+ return true;
for (i = 0; i < n; i++)
- mat[r2][i] += const1 * mat[r1][i];
+ {
+ bool ovf;
+ lambda_int tem = mul_hwi (mat[r1][i], const1, &ovf);
+ if (ovf)
+ return false;
+ lambda_int tem2 = add_hwi (mat[r2][i], tem, &ovf);
+ if (ovf || tem2 == HOST_WIDE_INT_MIN)
+ return false;
+ mat[r2][i] = tem2;
+ }
+
+ return true;
}
/* Multiply vector VEC1 of length SIZE by a constant CONST1,
@@ -4236,7 +4268,7 @@ lambda_vector_equal (lambda_vector vec1, lambda_vector vec2, int size)
Ref: Algorithm 2.1 page 33 in "Loop Transformations for
Restructuring Compilers" Utpal Banerjee. */
-static void
+static bool
lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
lambda_matrix S, lambda_matrix U)
{
@@ -4254,24 +4286,26 @@ lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
{
while (S[i][j] != 0)
{
- lambda_int sigma, factor, a, b;
+ lambda_int factor, a, b;
a = S[i-1][j];
b = S[i][j];
- sigma = (a * b < 0) ? -1: 1;
- a = abs_hwi (a);
- b = abs_hwi (b);
- factor = sigma * (a / b);
+ gcc_assert (a != HOST_WIDE_INT_MIN);
+ factor = a / b;
- lambda_matrix_row_add (S, n, i, i-1, -factor);
+ if (!lambda_matrix_row_add (S, n, i, i-1, -factor))
+ return false;
std::swap (S[i], S[i-1]);
- lambda_matrix_row_add (U, m, i, i-1, -factor);
+ if (!lambda_matrix_row_add (U, m, i, i-1, -factor))
+ return false;
std::swap (U[i], U[i-1]);
}
}
}
}
+
+ return true;
}
/* Determines the overlapping elements due to accesses CHREC_A and
@@ -4287,7 +4321,7 @@ analyze_subscript_affine_affine (tree chrec_a,
tree *last_conflicts)
{
unsigned nb_vars_a, nb_vars_b, dim;
- HOST_WIDE_INT gamma, gcd_alpha_beta;
+ lambda_int gamma, gcd_alpha_beta;
lambda_matrix A, U, S;
struct obstack scratch_obstack;
@@ -4388,7 +4422,13 @@ analyze_subscript_affine_affine (tree chrec_a,
}
/* U.A = S */
- lambda_matrix_right_hermite (A, dim, 1, S, U);
+ if (!lambda_matrix_right_hermite (A, dim, 1, S, U))
+ {
+ *overlaps_a = conflict_fn_not_known ();
+ *overlaps_b = conflict_fn_not_known ();
+ *last_conflicts = chrec_dont_know;
+ goto end_analyze_subs_aa;
+ }
if (S[0][0] < 0)
{
@@ -4914,10 +4954,7 @@ analyze_overlapping_iterations (tree chrec_a,
static void
save_dist_v (struct data_dependence_relation *ddr, lambda_vector dist_v)
{
- unsigned i;
- lambda_vector v;
-
- FOR_EACH_VEC_ELT (DDR_DIST_VECTS (ddr), i, v)
+ for (lambda_vector v : DDR_DIST_VECTS (ddr))
if (lambda_vector_equal (v, dist_v, DDR_NB_LOOPS (ddr)))
return;
@@ -4929,10 +4966,7 @@ save_dist_v (struct data_dependence_relation *ddr, lambda_vector dist_v)
static void
save_dir_v (struct data_dependence_relation *ddr, lambda_vector dir_v)
{
- unsigned i;
- lambda_vector v;
-
- FOR_EACH_VEC_ELT (DDR_DIR_VECTS (ddr), i, v)
+ for (lambda_vector v : DDR_DIR_VECTS (ddr))
if (lambda_vector_equal (v, dir_v, DDR_NB_LOOPS (ddr)))
return;
@@ -5055,6 +5089,8 @@ build_classic_dist_vector_1 (struct data_dependence_relation *ddr,
non_affine_dependence_relation (ddr);
return false;
}
+ else
+ *init_b = true;
}
return true;
@@ -5067,10 +5103,7 @@ static bool
invariant_access_functions (const struct data_dependence_relation *ddr,
int lnum)
{
- unsigned i;
- subscript *sub;
-
- FOR_EACH_VEC_ELT (DDR_SUBSCRIPTS (ddr), i, sub)
+ for (subscript *sub : DDR_SUBSCRIPTS (ddr))
if (!evolution_function_is_invariant_p (SUB_ACCESS_FN (sub, 0), lnum)
|| !evolution_function_is_invariant_p (SUB_ACCESS_FN (sub, 1), lnum))
return false;
@@ -5239,10 +5272,7 @@ add_distance_for_zero_overlaps (struct data_dependence_relation *ddr)
static inline bool
same_access_functions (const struct data_dependence_relation *ddr)
{
- unsigned i;
- subscript *sub;
-
- FOR_EACH_VEC_ELT (DDR_SUBSCRIPTS (ddr), i, sub)
+ for (subscript *sub : DDR_SUBSCRIPTS (ddr))
if (!eq_evolutions_p (SUB_ACCESS_FN (sub, 0),
SUB_ACCESS_FN (sub, 1)))
return false;
@@ -5519,11 +5549,8 @@ static bool
access_functions_are_affine_or_constant_p (const struct data_reference *a,
const class loop *loop_nest)
{
- unsigned int i;
vec<tree> fns = DR_ACCESS_FNS (a);
- tree t;
-
- FOR_EACH_VEC_ELT (fns, i, t)
+ for (tree t : fns)
if (!evolution_function_is_invariant_p (t, loop_nest->num)
&& !evolution_function_is_affine_multivariate_p (t, loop_nest->num))
return false;
@@ -5550,9 +5577,13 @@ compute_affine_dependence (struct data_dependence_relation *ddr,
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "(compute_affine_dependence\n");
- fprintf (dump_file, " stmt_a: ");
+ fprintf (dump_file, " ref_a: ");
+ print_generic_expr (dump_file, DR_REF (dra));
+ fprintf (dump_file, ", stmt_a: ");
print_gimple_stmt (dump_file, DR_STMT (dra), 0, TDF_SLIM);
- fprintf (dump_file, " stmt_b: ");
+ fprintf (dump_file, " ref_b: ");
+ print_generic_expr (dump_file, DR_REF (drb));
+ fprintf (dump_file, ", stmt_b: ");
print_gimple_stmt (dump_file, DR_STMT (drb), 0, TDF_SLIM);
}
@@ -5602,9 +5633,9 @@ compute_affine_dependence (struct data_dependence_relation *ddr,
is small enough to be handled. */
bool
-compute_all_dependences (vec<data_reference_p> datarefs,
+compute_all_dependences (const vec<data_reference_p> &datarefs,
vec<ddr_p> *dependence_relations,
- vec<loop_p> loop_nest,
+ const vec<loop_p> &loop_nest,
bool compute_self_and_rr)
{
struct data_dependence_relation *ddr;
@@ -5830,20 +5861,18 @@ opt_result
find_data_references_in_stmt (class loop *nest, gimple *stmt,
vec<data_reference_p> *datarefs)
{
- unsigned i;
auto_vec<data_ref_loc, 2> references;
- data_ref_loc *ref;
data_reference_p dr;
if (get_references_in_stmt (stmt, &references))
return opt_result::failure_at (stmt, "statement clobbers memory: %G",
stmt);
- FOR_EACH_VEC_ELT (references, i, ref)
+ for (const data_ref_loc &ref : references)
{
dr = create_data_ref (nest ? loop_preheader_edge (nest) : NULL,
- loop_containing_stmt (stmt), ref->ref,
- stmt, ref->is_read, ref->is_conditional_in_stmt);
+ loop_containing_stmt (stmt), ref.ref,
+ stmt, ref.is_read, ref.is_conditional_in_stmt);
gcc_assert (dr != NULL);
datarefs->safe_push (dr);
}
@@ -5861,19 +5890,17 @@ bool
graphite_find_data_references_in_stmt (edge nest, loop_p loop, gimple *stmt,
vec<data_reference_p> *datarefs)
{
- unsigned i;
auto_vec<data_ref_loc, 2> references;
- data_ref_loc *ref;
bool ret = true;
data_reference_p dr;
if (get_references_in_stmt (stmt, &references))
return false;
- FOR_EACH_VEC_ELT (references, i, ref)
+ for (const data_ref_loc &ref : references)
{
- dr = create_data_ref (nest, loop, ref->ref, stmt, ref->is_read,
- ref->is_conditional_in_stmt);
+ dr = create_data_ref (nest, loop, ref.ref, stmt, ref.is_read,
+ ref.is_conditional_in_stmt);
gcc_assert (dr != NULL);
datarefs->safe_push (dr);
}
@@ -6179,12 +6206,9 @@ free_dependence_relation (struct data_dependence_relation *ddr)
DEPENDENCE_RELATIONS. */
void
-free_dependence_relations (vec<ddr_p> dependence_relations)
+free_dependence_relations (vec<ddr_p>& dependence_relations)
{
- unsigned int i;
- struct data_dependence_relation *ddr;
-
- FOR_EACH_VEC_ELT (dependence_relations, i, ddr)
+ for (data_dependence_relation *ddr : dependence_relations)
if (ddr)
free_dependence_relation (ddr);
@@ -6194,12 +6218,9 @@ free_dependence_relations (vec<ddr_p> dependence_relations)
/* Free the memory used by the data references from DATAREFS. */
void
-free_data_refs (vec<data_reference_p> datarefs)
+free_data_refs (vec<data_reference_p>& datarefs)
{
- unsigned int i;
- struct data_reference *dr;
-
- FOR_EACH_VEC_ELT (datarefs, i, dr)
+ for (data_reference *dr : datarefs)
free_data_ref (dr);
datarefs.release ();
}
@@ -6241,12 +6262,19 @@ dr_step_indicator (struct data_reference *dr, int useful_min)
/* Get the range of values that the unconverted step actually has. */
wide_int step_min, step_max;
+ value_range vr;
if (TREE_CODE (step) != SSA_NAME
- || get_range_info (step, &step_min, &step_max) != VR_RANGE)
+ || !get_range_query (cfun)->range_of_expr (vr, step)
+ || vr.kind () != VR_RANGE)
{
step_min = wi::to_wide (TYPE_MIN_VALUE (type));
step_max = wi::to_wide (TYPE_MAX_VALUE (type));
}
+ else
+ {
+ step_min = vr.lower_bound ();
+ step_max = vr.upper_bound ();
+ }
/* Check whether the unconverted step has an acceptable range. */
signop sgn = TYPE_SIGN (type);