Commit 079b4a9c by Richard Sandiford Committed by Richard Sandiford

poly_int: prune_runtime_alias_test_list

This patch makes prune_runtime_alias_test_list take the iteration
factor as a poly_int and tracks polynomial offsets internally
as well.

2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* tree-data-ref.h (prune_runtime_alias_test_list): Take the
	factor as a poly_uint64 rather than an unsigned HOST_WIDE_INT.
	* tree-data-ref.c (prune_runtime_alias_test_list): Likewise.
	Track polynomial offsets.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>

From-SVN: r255936
parent 8944b5b3
...@@ -2,6 +2,15 @@ ...@@ -2,6 +2,15 @@
Alan Hayward <alan.hayward@arm.com> Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com> David Sherwood <david.sherwood@arm.com>
* tree-data-ref.h (prune_runtime_alias_test_list): Take the
factor as a poly_uint64 rather than an unsigned HOST_WIDE_INT.
* tree-data-ref.c (prune_runtime_alias_test_list): Likewise.
Track polynomial offsets.
2017-12-21 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* tree-vect-data-refs.c (vect_compute_data_ref_alignment): * tree-vect-data-refs.c (vect_compute_data_ref_alignment):
Treat drb->init as a poly_int. Fail if its misalignment wrt Treat drb->init as a poly_int. Fail if its misalignment wrt
vector_alignment isn't known. vector_alignment isn't known.
...@@ -1417,7 +1417,7 @@ comp_dr_with_seg_len_pair (const void *pa_, const void *pb_) ...@@ -1417,7 +1417,7 @@ comp_dr_with_seg_len_pair (const void *pa_, const void *pb_)
void void
prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs, prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
unsigned HOST_WIDE_INT factor) poly_uint64 factor)
{ {
/* Sort the collected data ref pairs so that we can scan them once to /* Sort the collected data ref pairs so that we can scan them once to
combine all possible aliasing checks. */ combine all possible aliasing checks. */
...@@ -1462,51 +1462,63 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs, ...@@ -1462,51 +1462,63 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
std::swap (dr_a2, dr_b2); std::swap (dr_a2, dr_b2);
} }
poly_int64 init_a1, init_a2;
if (!operand_equal_p (DR_BASE_ADDRESS (dr_a1->dr), if (!operand_equal_p (DR_BASE_ADDRESS (dr_a1->dr),
DR_BASE_ADDRESS (dr_a2->dr), 0) DR_BASE_ADDRESS (dr_a2->dr), 0)
|| !operand_equal_p (DR_OFFSET (dr_a1->dr), || !operand_equal_p (DR_OFFSET (dr_a1->dr),
DR_OFFSET (dr_a2->dr), 0) DR_OFFSET (dr_a2->dr), 0)
|| !tree_fits_shwi_p (DR_INIT (dr_a1->dr)) || !poly_int_tree_p (DR_INIT (dr_a1->dr), &init_a1)
|| !tree_fits_shwi_p (DR_INIT (dr_a2->dr))) || !poly_int_tree_p (DR_INIT (dr_a2->dr), &init_a2))
continue; continue;
/* Don't combine if we can't tell which one comes first. */
if (!ordered_p (init_a1, init_a2))
continue;
/* Make sure dr_a1 starts left of dr_a2. */
if (maybe_gt (init_a1, init_a2))
{
std::swap (*dr_a1, *dr_a2);
std::swap (init_a1, init_a2);
}
/* Only merge const step data references. */ /* Only merge const step data references. */
if (TREE_CODE (DR_STEP (dr_a1->dr)) != INTEGER_CST poly_int64 step_a1, step_a2;
|| TREE_CODE (DR_STEP (dr_a2->dr)) != INTEGER_CST) if (!poly_int_tree_p (DR_STEP (dr_a1->dr), &step_a1)
|| !poly_int_tree_p (DR_STEP (dr_a2->dr), &step_a2))
continue; continue;
/* DR_A1 and DR_A2 must goes in the same direction. */ bool neg_step = maybe_lt (step_a1, 0) || maybe_lt (step_a2, 0);
if (tree_int_cst_compare (DR_STEP (dr_a1->dr), size_zero_node)
!= tree_int_cst_compare (DR_STEP (dr_a2->dr), size_zero_node)) /* DR_A1 and DR_A2 must go in the same direction. */
if (neg_step && (maybe_gt (step_a1, 0) || maybe_gt (step_a2, 0)))
continue; continue;
bool neg_step poly_uint64 seg_len_a1 = 0, seg_len_a2 = 0;
= (tree_int_cst_compare (DR_STEP (dr_a1->dr), size_zero_node) < 0); bool const_seg_len_a1 = poly_int_tree_p (dr_a1->seg_len,
&seg_len_a1);
bool const_seg_len_a2 = poly_int_tree_p (dr_a2->seg_len,
&seg_len_a2);
/* We need to compute merged segment length at compilation time for /* We need to compute merged segment length at compilation time for
dr_a1 and dr_a2, which is impossible if either one has non-const dr_a1 and dr_a2, which is impossible if either one has non-const
segment length. */ segment length. */
if ((!tree_fits_uhwi_p (dr_a1->seg_len) if ((!const_seg_len_a1 || !const_seg_len_a2)
|| !tree_fits_uhwi_p (dr_a2->seg_len)) && maybe_ne (step_a1, step_a2))
&& tree_int_cst_compare (DR_STEP (dr_a1->dr),
DR_STEP (dr_a2->dr)) != 0)
continue; continue;
/* Make sure dr_a1 starts left of dr_a2. */
if (tree_int_cst_lt (DR_INIT (dr_a2->dr), DR_INIT (dr_a1->dr)))
std::swap (*dr_a1, *dr_a2);
bool do_remove = false; bool do_remove = false;
wide_int diff = (wi::to_wide (DR_INIT (dr_a2->dr)) poly_uint64 diff = init_a2 - init_a1;
- wi::to_wide (DR_INIT (dr_a1->dr))); poly_uint64 min_seg_len_b;
wide_int min_seg_len_b;
tree new_seg_len; tree new_seg_len;
if (TREE_CODE (dr_b1->seg_len) == INTEGER_CST) if (!poly_int_tree_p (dr_b1->seg_len, &min_seg_len_b))
min_seg_len_b = wi::abs (wi::to_wide (dr_b1->seg_len)); {
else tree step_b = DR_STEP (dr_b1->dr);
min_seg_len_b if (!tree_fits_shwi_p (step_b))
= factor * wi::abs (wi::to_wide (DR_STEP (dr_b1->dr))); continue;
min_seg_len_b = factor * abs_hwi (tree_to_shwi (step_b));
}
/* Now we try to merge alias check dr_a1 & dr_b and dr_a2 & dr_b. /* Now we try to merge alias check dr_a1 & dr_b and dr_a2 & dr_b.
...@@ -1543,26 +1555,24 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs, ...@@ -1543,26 +1555,24 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
if (neg_step) if (neg_step)
{ {
/* Adjust diff according to access size of both references. */ /* Adjust diff according to access size of both references. */
tree size_a1 = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a1->dr))); diff += tree_to_poly_uint64
tree size_a2 = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a2->dr))); (TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a2->dr))));
diff += wi::to_wide (size_a2) - wi::to_wide (size_a1); diff -= tree_to_poly_uint64
(TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a1->dr))));
/* Case A.1. */ /* Case A.1. */
if (wi::leu_p (diff, min_seg_len_b) if (known_le (diff, min_seg_len_b)
/* Case A.2 and B combined. */ /* Case A.2 and B combined. */
|| (tree_fits_uhwi_p (dr_a2->seg_len))) || const_seg_len_a2)
{ {
if (tree_fits_uhwi_p (dr_a1->seg_len) if (const_seg_len_a1 || const_seg_len_a2)
&& tree_fits_uhwi_p (dr_a2->seg_len)) new_seg_len
{ = build_int_cstu (sizetype,
wide_int min_len lower_bound (seg_len_a1 - diff,
= wi::umin (wi::to_wide (dr_a1->seg_len) - diff, seg_len_a2));
wi::to_wide (dr_a2->seg_len));
new_seg_len = wide_int_to_tree (sizetype, min_len);
}
else else
new_seg_len new_seg_len
= size_binop (MINUS_EXPR, dr_a2->seg_len, = size_binop (MINUS_EXPR, dr_a2->seg_len,
wide_int_to_tree (sizetype, diff)); build_int_cstu (sizetype, diff));
dr_a2->seg_len = new_seg_len; dr_a2->seg_len = new_seg_len;
do_remove = true; do_remove = true;
...@@ -1571,22 +1581,19 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs, ...@@ -1571,22 +1581,19 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
else else
{ {
/* Case A.1. */ /* Case A.1. */
if (wi::leu_p (diff, min_seg_len_b) if (known_le (diff, min_seg_len_b)
/* Case A.2 and B combined. */ /* Case A.2 and B combined. */
|| (tree_fits_uhwi_p (dr_a1->seg_len))) || const_seg_len_a1)
{ {
if (tree_fits_uhwi_p (dr_a1->seg_len) if (const_seg_len_a1 && const_seg_len_a2)
&& tree_fits_uhwi_p (dr_a2->seg_len)) new_seg_len
{ = build_int_cstu (sizetype,
wide_int max_len upper_bound (seg_len_a2 + diff,
= wi::umax (wi::to_wide (dr_a2->seg_len) + diff, seg_len_a1));
wi::to_wide (dr_a1->seg_len));
new_seg_len = wide_int_to_tree (sizetype, max_len);
}
else else
new_seg_len new_seg_len
= size_binop (PLUS_EXPR, dr_a2->seg_len, = size_binop (PLUS_EXPR, dr_a2->seg_len,
wide_int_to_tree (sizetype, diff)); build_int_cstu (sizetype, diff));
dr_a1->seg_len = new_seg_len; dr_a1->seg_len = new_seg_len;
do_remove = true; do_remove = true;
......
...@@ -472,7 +472,7 @@ extern bool dr_equal_offsets_p (struct data_reference *, ...@@ -472,7 +472,7 @@ extern bool dr_equal_offsets_p (struct data_reference *,
extern bool runtime_alias_check_p (ddr_p, struct loop *, bool); extern bool runtime_alias_check_p (ddr_p, struct loop *, bool);
extern int data_ref_compare_tree (tree, tree); extern int data_ref_compare_tree (tree, tree);
extern void prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *, extern void prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *,
unsigned HOST_WIDE_INT); poly_uint64);
extern void create_runtime_alias_checks (struct loop *, extern void create_runtime_alias_checks (struct loop *,
vec<dr_with_seg_len_pair_t> *, tree*); vec<dr_with_seg_len_pair_t> *, tree*);
/* Return true when the base objects of data references A and B are /* Return true when the base objects of data references A and B are
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment