aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-data-refs.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2018-01-03 07:16:47 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2018-01-03 07:16:47 +0000
commitb064d4f9d6cb163da32d19cb172cbc4a5fffb39a (patch)
tree0e5cc0305a12b6479ab3575e35e4626e455b3389 /gcc/tree-vect-data-refs.c
parentdad55d7014374121fd75112014ccadcfb9653182 (diff)
downloadgcc-b064d4f9d6cb163da32d19cb172cbc4a5fffb39a.zip
gcc-b064d4f9d6cb163da32d19cb172cbc4a5fffb39a.tar.gz
gcc-b064d4f9d6cb163da32d19cb172cbc4a5fffb39a.tar.bz2
poly_int: vect_no_alias_p
This patch replaces the two-state vect_no_alias_p with a three-state vect_compile_time_alias that handles polynomial segment lengths. 2018-01-03 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> gcc/ * tree-vect-data-refs.c (vect_no_alias_p): Replace with... (vect_compile_time_alias): ...this new function. Do the calculation on poly_ints rather than trees. (vect_prune_runtime_alias_test_list): Update call accordingly. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r256142
Diffstat (limited to 'gcc/tree-vect-data-refs.c')
-rw-r--r--gcc/tree-vect-data-refs.c80
1 files changed, 41 insertions, 39 deletions
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 2e02be5..0aa0bfd 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -3001,52 +3001,49 @@ vect_vfa_segment_size (struct data_reference *dr, tree length_factor)
/* Function vect_no_alias_p.
- Given data references A and B with equal base and offset, the alias
- relation can be decided at compilation time, return TRUE if they do
- not alias to each other; return FALSE otherwise. SEGMENT_LENGTH_A
+ Given data references A and B with equal base and offset, see whether
+ the alias relation can be decided at compilation time. Return 1 if
+ it can and the references alias, 0 if it can and the references do
+ not alias, and -1 if we cannot decide at compile time. SEGMENT_LENGTH_A
and SEGMENT_LENGTH_B are the memory lengths accessed by A and B
respectively. */
-static bool
-vect_no_alias_p (struct data_reference *a, struct data_reference *b,
- tree segment_length_a, tree segment_length_b)
+static int
+vect_compile_time_alias (struct data_reference *a, struct data_reference *b,
+ tree segment_length_a, tree segment_length_b)
{
- gcc_assert (TREE_CODE (DR_INIT (a)) == INTEGER_CST
- && TREE_CODE (DR_INIT (b)) == INTEGER_CST);
- if (tree_int_cst_equal (DR_INIT (a), DR_INIT (b)))
- return false;
+ poly_offset_int offset_a = wi::to_poly_offset (DR_INIT (a));
+ poly_offset_int offset_b = wi::to_poly_offset (DR_INIT (b));
+ poly_uint64 const_length_a;
+ poly_uint64 const_length_b;
- tree seg_a_min = DR_INIT (a);
- tree seg_a_max = fold_build2 (PLUS_EXPR, TREE_TYPE (seg_a_min),
- seg_a_min, segment_length_a);
/* For negative step, we need to adjust address range by TYPE_SIZE_UNIT
bytes, e.g., int a[3] -> a[1] range is [a+4, a+16) instead of
[a, a+12) */
if (tree_int_cst_compare (DR_STEP (a), size_zero_node) < 0)
{
- tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (a)));
- seg_a_min = fold_build2 (PLUS_EXPR, TREE_TYPE (seg_a_max),
- seg_a_max, unit_size);
- seg_a_max = fold_build2 (PLUS_EXPR, TREE_TYPE (DR_INIT (a)),
- DR_INIT (a), unit_size);
+ const_length_a = (-wi::to_poly_wide (segment_length_a)).force_uhwi ();
+ offset_a = (offset_a + vect_get_scalar_dr_size (a)) - const_length_a;
}
- tree seg_b_min = DR_INIT (b);
- tree seg_b_max = fold_build2 (PLUS_EXPR, TREE_TYPE (seg_b_min),
- seg_b_min, segment_length_b);
+ else
+ const_length_a = tree_to_poly_uint64 (segment_length_a);
if (tree_int_cst_compare (DR_STEP (b), size_zero_node) < 0)
{
- tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (b)));
- seg_b_min = fold_build2 (PLUS_EXPR, TREE_TYPE (seg_b_max),
- seg_b_max, unit_size);
- seg_b_max = fold_build2 (PLUS_EXPR, TREE_TYPE (DR_INIT (b)),
- DR_INIT (b), unit_size);
+ const_length_b = (-wi::to_poly_wide (segment_length_b)).force_uhwi ();
+ offset_b = (offset_b + vect_get_scalar_dr_size (b)) - const_length_b;
}
+ else
+ const_length_b = tree_to_poly_uint64 (segment_length_b);
- if (tree_int_cst_le (seg_a_max, seg_b_min)
- || tree_int_cst_le (seg_b_max, seg_a_min))
- return true;
+ if (ranges_known_overlap_p (offset_a, const_length_a,
+ offset_b, const_length_b))
+ return 1;
- return false;
+ if (!ranges_maybe_overlap_p (offset_a, const_length_a,
+ offset_b, const_length_b))
+ return 0;
+
+ return -1;
}
/* Return true if the minimum nonzero dependence distance for loop LOOP_DEPTH
@@ -3188,21 +3185,26 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
comp_res = data_ref_compare_tree (DR_OFFSET (dr_a),
DR_OFFSET (dr_b));
- /* Alias is known at compilation time. */
+ /* See whether the alias is known at compilation time. */
if (comp_res == 0
&& TREE_CODE (DR_STEP (dr_a)) == INTEGER_CST
&& TREE_CODE (DR_STEP (dr_b)) == INTEGER_CST
- && TREE_CODE (segment_length_a) == INTEGER_CST
- && TREE_CODE (segment_length_b) == INTEGER_CST)
+ && poly_int_tree_p (segment_length_a)
+ && poly_int_tree_p (segment_length_b))
{
- if (vect_no_alias_p (dr_a, dr_b, segment_length_a, segment_length_b))
+ int res = vect_compile_time_alias (dr_a, dr_b,
+ segment_length_a,
+ segment_length_b);
+ if (res == 0)
continue;
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "not vectorized: compilation time alias.\n");
-
- return false;
+ if (res == 1)
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "not vectorized: compilation time alias.\n");
+ return false;
+ }
}
dr_with_seg_len_pair_t dr_with_seg_len_pair