* tree-vect-loop-manip.c (create_intersect_range_checks_index)
(create_intersect_range_checks): Move from ... * tree-data-ref.c (create_intersect_range_checks_index) (create_intersect_range_checks): ... to here. (create_runtime_alias_checks): New function factored from ... * tree-vect-loop-manip.c (vect_create_cond_for_alias_checks): ... here. Call above function. * tree-data-ref.h (create_runtime_alias_checks): New function. From-SVN: r248726
This commit is contained in:
parent
c7d7e2227f
commit
9cbd2d979c
@ -1,3 +1,14 @@
|
||||
2017-05-31 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
* tree-vect-loop-manip.c (create_intersect_range_checks_index)
|
||||
(create_intersect_range_checks): Move from ...
|
||||
* tree-data-ref.c (create_intersect_range_checks_index)
|
||||
(create_intersect_range_checks): ... to here.
|
||||
(create_runtime_alias_checks): New function factored from ...
|
||||
* tree-vect-loop-manip.c (vect_create_cond_for_alias_checks): ...
|
||||
here. Call above function.
|
||||
* tree-data-ref.h (create_runtime_alias_checks): New function.
|
||||
|
||||
2017-05-31 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
* tree-data-ref.c (prune_runtime_alias_test_list): Relax minimal
|
||||
|
@ -1470,6 +1470,231 @@ prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *alias_pairs,
|
||||
}
|
||||
}
|
||||
|
||||
/* Given LOOP's two data references and segment lengths described by DR_A
|
||||
and DR_B, create expression checking if the two addresses ranges intersect
|
||||
with each other based on index of the two addresses. This can only be
|
||||
done if DR_A and DR_B referring to the same (array) object and the index
|
||||
is the only difference. For example:
|
||||
|
||||
DR_A DR_B
|
||||
data-ref arr[i] arr[j]
|
||||
base_object arr arr
|
||||
index {i_0, +, 1}_loop {j_0, +, 1}_loop
|
||||
|
||||
The addresses and their index are like:
|
||||
|
||||
|<- ADDR_A ->| |<- ADDR_B ->|
|
||||
------------------------------------------------------->
|
||||
| | | | | | | | | |
|
||||
------------------------------------------------------->
|
||||
i_0 ... i_0+4 j_0 ... j_0+4
|
||||
|
||||
We can create expression based on index rather than address:
|
||||
|
||||
(i_0 + 4 < j_0 || j_0 + 4 < i_0)
|
||||
|
||||
Note evolution step of index needs to be considered in comparison. */
|
||||
|
||||
static bool
|
||||
create_intersect_range_checks_index (struct loop *loop, tree *cond_expr,
|
||||
const dr_with_seg_len& dr_a,
|
||||
const dr_with_seg_len& dr_b)
|
||||
{
|
||||
if (integer_zerop (DR_STEP (dr_a.dr))
|
||||
|| integer_zerop (DR_STEP (dr_b.dr))
|
||||
|| DR_NUM_DIMENSIONS (dr_a.dr) != DR_NUM_DIMENSIONS (dr_b.dr))
|
||||
return false;
|
||||
|
||||
if (!tree_fits_uhwi_p (dr_a.seg_len) || !tree_fits_uhwi_p (dr_b.seg_len))
|
||||
return false;
|
||||
|
||||
if (!tree_fits_shwi_p (DR_STEP (dr_a.dr)))
|
||||
return false;
|
||||
|
||||
if (!operand_equal_p (DR_BASE_OBJECT (dr_a.dr), DR_BASE_OBJECT (dr_b.dr), 0))
|
||||
return false;
|
||||
|
||||
if (!operand_equal_p (DR_STEP (dr_a.dr), DR_STEP (dr_b.dr), 0))
|
||||
return false;
|
||||
|
||||
gcc_assert (TREE_CODE (DR_STEP (dr_a.dr)) == INTEGER_CST);
|
||||
|
||||
bool neg_step = tree_int_cst_compare (DR_STEP (dr_a.dr), size_zero_node) < 0;
|
||||
unsigned HOST_WIDE_INT abs_step
|
||||
= absu_hwi (tree_to_shwi (DR_STEP (dr_a.dr)));
|
||||
|
||||
unsigned HOST_WIDE_INT seg_len1 = tree_to_uhwi (dr_a.seg_len);
|
||||
unsigned HOST_WIDE_INT seg_len2 = tree_to_uhwi (dr_b.seg_len);
|
||||
/* Infer the number of iterations with which the memory segment is accessed
|
||||
by DR. In other words, alias is checked if memory segment accessed by
|
||||
DR_A in some iterations intersect with memory segment accessed by DR_B
|
||||
in the same amount iterations.
|
||||
Note segnment length is a linear function of number of iterations with
|
||||
DR_STEP as the coefficient. */
|
||||
unsigned HOST_WIDE_INT niter_len1 = (seg_len1 + abs_step - 1) / abs_step;
|
||||
unsigned HOST_WIDE_INT niter_len2 = (seg_len2 + abs_step - 1) / abs_step;
|
||||
|
||||
unsigned int i;
|
||||
for (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);
|
||||
/* Two indices must be the same if they are not scev, or not scev wrto
|
||||
current loop being vecorized. */
|
||||
if (TREE_CODE (access1) != POLYNOMIAL_CHREC
|
||||
|| TREE_CODE (access2) != POLYNOMIAL_CHREC
|
||||
|| CHREC_VARIABLE (access1) != (unsigned)loop->num
|
||||
|| CHREC_VARIABLE (access2) != (unsigned)loop->num)
|
||||
{
|
||||
if (operand_equal_p (access1, access2, 0))
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
/* The two indices must have the same step. */
|
||||
if (!operand_equal_p (CHREC_RIGHT (access1), CHREC_RIGHT (access2), 0))
|
||||
return false;
|
||||
|
||||
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);
|
||||
|
||||
tree min1 = CHREC_LEFT (access1);
|
||||
tree min2 = CHREC_LEFT (access2);
|
||||
if (!types_compatible_p (TREE_TYPE (min1), TREE_TYPE (min2)))
|
||||
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. */
|
||||
tree idx_len1 = fold_build2 (MULT_EXPR, TREE_TYPE (min1), idx_step,
|
||||
build_int_cst (TREE_TYPE (min1),
|
||||
niter_len1));
|
||||
tree idx_len2 = fold_build2 (MULT_EXPR, TREE_TYPE (min2), idx_step,
|
||||
build_int_cst (TREE_TYPE (min2),
|
||||
niter_len2));
|
||||
tree max1 = fold_build2 (PLUS_EXPR, TREE_TYPE (min1), min1, idx_len1);
|
||||
tree max2 = fold_build2 (PLUS_EXPR, TREE_TYPE (min2), min2, idx_len2);
|
||||
/* Adjust ranges for negative step. */
|
||||
if (neg_step)
|
||||
{
|
||||
min1 = fold_build2 (MINUS_EXPR, TREE_TYPE (min1), max1, idx_step);
|
||||
max1 = fold_build2 (MINUS_EXPR, TREE_TYPE (min1),
|
||||
CHREC_LEFT (access1), idx_step);
|
||||
min2 = fold_build2 (MINUS_EXPR, TREE_TYPE (min2), max2, idx_step);
|
||||
max2 = fold_build2 (MINUS_EXPR, TREE_TYPE (min2),
|
||||
CHREC_LEFT (access2), idx_step);
|
||||
}
|
||||
tree part_cond_expr
|
||||
= fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
|
||||
fold_build2 (LE_EXPR, boolean_type_node, max1, min2),
|
||||
fold_build2 (LE_EXPR, boolean_type_node, max2, min1));
|
||||
if (*cond_expr)
|
||||
*cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
||||
*cond_expr, part_cond_expr);
|
||||
else
|
||||
*cond_expr = part_cond_expr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Given two data references and segment lengths described by DR_A and DR_B,
|
||||
create expression checking if the two addresses ranges intersect with
|
||||
each other:
|
||||
|
||||
((DR_A_addr_0 + DR_A_segment_length_0) <= DR_B_addr_0)
|
||||
|| (DR_B_addr_0 + DER_B_segment_length_0) <= DR_A_addr_0)) */
|
||||
|
||||
static void
|
||||
create_intersect_range_checks (struct loop *loop, tree *cond_expr,
|
||||
const dr_with_seg_len& dr_a,
|
||||
const dr_with_seg_len& dr_b)
|
||||
{
|
||||
*cond_expr = NULL_TREE;
|
||||
if (create_intersect_range_checks_index (loop, cond_expr, dr_a, dr_b))
|
||||
return;
|
||||
|
||||
tree segment_length_a = dr_a.seg_len;
|
||||
tree segment_length_b = dr_b.seg_len;
|
||||
tree addr_base_a = DR_BASE_ADDRESS (dr_a.dr);
|
||||
tree addr_base_b = DR_BASE_ADDRESS (dr_b.dr);
|
||||
tree offset_a = DR_OFFSET (dr_a.dr), offset_b = DR_OFFSET (dr_b.dr);
|
||||
|
||||
offset_a = fold_build2 (PLUS_EXPR, TREE_TYPE (offset_a),
|
||||
offset_a, DR_INIT (dr_a.dr));
|
||||
offset_b = fold_build2 (PLUS_EXPR, TREE_TYPE (offset_b),
|
||||
offset_b, DR_INIT (dr_b.dr));
|
||||
addr_base_a = fold_build_pointer_plus (addr_base_a, offset_a);
|
||||
addr_base_b = fold_build_pointer_plus (addr_base_b, offset_b);
|
||||
|
||||
tree seg_a_min = addr_base_a;
|
||||
tree seg_a_max = fold_build_pointer_plus (addr_base_a, 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 (dr_a.dr), size_zero_node) < 0)
|
||||
{
|
||||
tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a.dr)));
|
||||
seg_a_min = fold_build_pointer_plus (seg_a_max, unit_size);
|
||||
seg_a_max = fold_build_pointer_plus (addr_base_a, unit_size);
|
||||
}
|
||||
|
||||
tree seg_b_min = addr_base_b;
|
||||
tree seg_b_max = fold_build_pointer_plus (addr_base_b, segment_length_b);
|
||||
if (tree_int_cst_compare (DR_STEP (dr_b.dr), size_zero_node) < 0)
|
||||
{
|
||||
tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_b.dr)));
|
||||
seg_b_min = fold_build_pointer_plus (seg_b_max, unit_size);
|
||||
seg_b_max = fold_build_pointer_plus (addr_base_b, unit_size);
|
||||
}
|
||||
*cond_expr
|
||||
= fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
|
||||
fold_build2 (LE_EXPR, boolean_type_node, seg_a_max, seg_b_min),
|
||||
fold_build2 (LE_EXPR, boolean_type_node, seg_b_max, seg_a_min));
|
||||
}
|
||||
|
||||
/* Create a conditional expression that represents the run-time checks for
|
||||
overlapping of address ranges represented by a list of data references
|
||||
pairs passed in ALIAS_PAIRS. Data references are in LOOP. The returned
|
||||
COND_EXPR is the conditional expression to be used in the if statement
|
||||
that controls which version of the loop gets executed at runtime. */
|
||||
|
||||
void
|
||||
create_runtime_alias_checks (struct loop *loop,
|
||||
vec<dr_with_seg_len_pair_t> *alias_pairs,
|
||||
tree * cond_expr)
|
||||
{
|
||||
tree part_cond_expr;
|
||||
|
||||
for (size_t i = 0, s = alias_pairs->length (); i < s; ++i)
|
||||
{
|
||||
const dr_with_seg_len& dr_a = (*alias_pairs)[i].first;
|
||||
const dr_with_seg_len& dr_b = (*alias_pairs)[i].second;
|
||||
|
||||
if (dump_enabled_p ())
|
||||
{
|
||||
dump_printf (MSG_NOTE, "create runtime check for data references ");
|
||||
dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a.dr));
|
||||
dump_printf (MSG_NOTE, " and ");
|
||||
dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b.dr));
|
||||
dump_printf (MSG_NOTE, "\n");
|
||||
}
|
||||
|
||||
/* Create condition expression for each pair data references. */
|
||||
create_intersect_range_checks (loop, &part_cond_expr, dr_a, dr_b);
|
||||
if (*cond_expr)
|
||||
*cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
||||
*cond_expr, part_cond_expr);
|
||||
else
|
||||
*cond_expr = part_cond_expr;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if OFFSET1 and OFFSET2 (DR_OFFSETs of some data-refs) are identical
|
||||
expressions. */
|
||||
static bool
|
||||
|
@ -371,6 +371,8 @@ extern bool dr_equal_offsets_p (struct data_reference *,
|
||||
extern int data_ref_compare_tree (tree, tree);
|
||||
extern void prune_runtime_alias_test_list (vec<dr_with_seg_len_pair_t> *,
|
||||
unsigned HOST_WIDE_INT);
|
||||
extern void create_runtime_alias_checks (struct loop *,
|
||||
vec<dr_with_seg_len_pair_t> *, tree*);
|
||||
/* Return true when the base objects of data references A and B are
|
||||
the same memory object. */
|
||||
|
||||
|
@ -2044,194 +2044,6 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
|
||||
*cond_expr = part_cond_expr;
|
||||
}
|
||||
|
||||
/* Given LOOP's two data references and segment lengths described by DR_A
|
||||
and DR_B, create expression checking if the two addresses ranges intersect
|
||||
with each other based on index of the two addresses. This can only be
|
||||
done if DR_A and DR_B referring to the same (array) object and the index
|
||||
is the only difference. For example:
|
||||
|
||||
DR_A DR_B
|
||||
data-ref arr[i] arr[j]
|
||||
base_object arr arr
|
||||
index {i_0, +, 1}_loop {j_0, +, 1}_loop
|
||||
|
||||
The addresses and their index are like:
|
||||
|
||||
|<- ADDR_A ->| |<- ADDR_B ->|
|
||||
------------------------------------------------------->
|
||||
| | | | | | | | | |
|
||||
------------------------------------------------------->
|
||||
i_0 ... i_0+4 j_0 ... j_0+4
|
||||
|
||||
We can create expression based on index rather than address:
|
||||
|
||||
(i_0 + 4 < j_0 || j_0 + 4 < i_0)
|
||||
|
||||
Note evolution step of index needs to be considered in comparison. */
|
||||
|
||||
static bool
|
||||
create_intersect_range_checks_index (struct loop *loop, tree *cond_expr,
|
||||
const dr_with_seg_len& dr_a,
|
||||
const dr_with_seg_len& dr_b)
|
||||
{
|
||||
if (integer_zerop (DR_STEP (dr_a.dr))
|
||||
|| integer_zerop (DR_STEP (dr_b.dr))
|
||||
|| DR_NUM_DIMENSIONS (dr_a.dr) != DR_NUM_DIMENSIONS (dr_b.dr))
|
||||
return false;
|
||||
|
||||
if (!tree_fits_uhwi_p (dr_a.seg_len) || !tree_fits_uhwi_p (dr_b.seg_len))
|
||||
return false;
|
||||
|
||||
if (!tree_fits_shwi_p (DR_STEP (dr_a.dr)))
|
||||
return false;
|
||||
|
||||
if (!operand_equal_p (DR_BASE_OBJECT (dr_a.dr), DR_BASE_OBJECT (dr_b.dr), 0))
|
||||
return false;
|
||||
|
||||
if (!operand_equal_p (DR_STEP (dr_a.dr), DR_STEP (dr_b.dr), 0))
|
||||
return false;
|
||||
|
||||
gcc_assert (TREE_CODE (DR_STEP (dr_a.dr)) == INTEGER_CST);
|
||||
|
||||
bool neg_step = tree_int_cst_compare (DR_STEP (dr_a.dr), size_zero_node) < 0;
|
||||
unsigned HOST_WIDE_INT abs_step
|
||||
= absu_hwi (tree_to_shwi (DR_STEP (dr_a.dr)));
|
||||
|
||||
unsigned HOST_WIDE_INT seg_len1 = tree_to_uhwi (dr_a.seg_len);
|
||||
unsigned HOST_WIDE_INT seg_len2 = tree_to_uhwi (dr_b.seg_len);
|
||||
/* Infer the number of iterations with which the memory segment is accessed
|
||||
by DR. In other words, alias is checked if memory segment accessed by
|
||||
DR_A in some iterations intersect with memory segment accessed by DR_B
|
||||
in the same amount iterations.
|
||||
Note segnment length is a linear function of number of iterations with
|
||||
DR_STEP as the coefficient. */
|
||||
unsigned HOST_WIDE_INT niter_len1 = (seg_len1 + abs_step - 1) / abs_step;
|
||||
unsigned HOST_WIDE_INT niter_len2 = (seg_len2 + abs_step - 1) / abs_step;
|
||||
|
||||
unsigned int i;
|
||||
for (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);
|
||||
/* Two indices must be the same if they are not scev, or not scev wrto
|
||||
current loop being vecorized. */
|
||||
if (TREE_CODE (access1) != POLYNOMIAL_CHREC
|
||||
|| TREE_CODE (access2) != POLYNOMIAL_CHREC
|
||||
|| CHREC_VARIABLE (access1) != (unsigned)loop->num
|
||||
|| CHREC_VARIABLE (access2) != (unsigned)loop->num)
|
||||
{
|
||||
if (operand_equal_p (access1, access2, 0))
|
||||
continue;
|
||||
|
||||
return false;
|
||||
}
|
||||
/* The two indices must have the same step. */
|
||||
if (!operand_equal_p (CHREC_RIGHT (access1), CHREC_RIGHT (access2), 0))
|
||||
return false;
|
||||
|
||||
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);
|
||||
|
||||
tree min1 = CHREC_LEFT (access1);
|
||||
tree min2 = CHREC_LEFT (access2);
|
||||
if (!types_compatible_p (TREE_TYPE (min1), TREE_TYPE (min2)))
|
||||
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. */
|
||||
tree idx_len1 = fold_build2 (MULT_EXPR, TREE_TYPE (min1), idx_step,
|
||||
build_int_cst (TREE_TYPE (min1),
|
||||
niter_len1));
|
||||
tree idx_len2 = fold_build2 (MULT_EXPR, TREE_TYPE (min2), idx_step,
|
||||
build_int_cst (TREE_TYPE (min2),
|
||||
niter_len2));
|
||||
tree max1 = fold_build2 (PLUS_EXPR, TREE_TYPE (min1), min1, idx_len1);
|
||||
tree max2 = fold_build2 (PLUS_EXPR, TREE_TYPE (min2), min2, idx_len2);
|
||||
/* Adjust ranges for negative step. */
|
||||
if (neg_step)
|
||||
{
|
||||
min1 = fold_build2 (MINUS_EXPR, TREE_TYPE (min1), max1, idx_step);
|
||||
max1 = fold_build2 (MINUS_EXPR, TREE_TYPE (min1),
|
||||
CHREC_LEFT (access1), idx_step);
|
||||
min2 = fold_build2 (MINUS_EXPR, TREE_TYPE (min2), max2, idx_step);
|
||||
max2 = fold_build2 (MINUS_EXPR, TREE_TYPE (min2),
|
||||
CHREC_LEFT (access2), idx_step);
|
||||
}
|
||||
tree part_cond_expr
|
||||
= fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
|
||||
fold_build2 (LE_EXPR, boolean_type_node, max1, min2),
|
||||
fold_build2 (LE_EXPR, boolean_type_node, max2, min1));
|
||||
if (*cond_expr)
|
||||
*cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
||||
*cond_expr, part_cond_expr);
|
||||
else
|
||||
*cond_expr = part_cond_expr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Given two data references and segment lengths described by DR_A and DR_B,
|
||||
create expression checking if the two addresses ranges intersect with
|
||||
each other:
|
||||
|
||||
((DR_A_addr_0 + DR_A_segment_length_0) <= DR_B_addr_0)
|
||||
|| (DR_B_addr_0 + DER_B_segment_length_0) <= DR_A_addr_0)) */
|
||||
|
||||
static void
|
||||
create_intersect_range_checks (struct loop *loop, tree *cond_expr,
|
||||
const dr_with_seg_len& dr_a,
|
||||
const dr_with_seg_len& dr_b)
|
||||
{
|
||||
*cond_expr = NULL_TREE;
|
||||
if (create_intersect_range_checks_index (loop, cond_expr, dr_a, dr_b))
|
||||
return;
|
||||
|
||||
tree segment_length_a = dr_a.seg_len;
|
||||
tree segment_length_b = dr_b.seg_len;
|
||||
tree addr_base_a = DR_BASE_ADDRESS (dr_a.dr);
|
||||
tree addr_base_b = DR_BASE_ADDRESS (dr_b.dr);
|
||||
tree offset_a = DR_OFFSET (dr_a.dr), offset_b = DR_OFFSET (dr_b.dr);
|
||||
|
||||
offset_a = fold_build2 (PLUS_EXPR, TREE_TYPE (offset_a),
|
||||
offset_a, DR_INIT (dr_a.dr));
|
||||
offset_b = fold_build2 (PLUS_EXPR, TREE_TYPE (offset_b),
|
||||
offset_b, DR_INIT (dr_b.dr));
|
||||
addr_base_a = fold_build_pointer_plus (addr_base_a, offset_a);
|
||||
addr_base_b = fold_build_pointer_plus (addr_base_b, offset_b);
|
||||
|
||||
tree seg_a_min = addr_base_a;
|
||||
tree seg_a_max = fold_build_pointer_plus (addr_base_a, 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 (dr_a.dr), size_zero_node) < 0)
|
||||
{
|
||||
tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_a.dr)));
|
||||
seg_a_min = fold_build_pointer_plus (seg_a_max, unit_size);
|
||||
seg_a_max = fold_build_pointer_plus (addr_base_a, unit_size);
|
||||
}
|
||||
|
||||
tree seg_b_min = addr_base_b;
|
||||
tree seg_b_max = fold_build_pointer_plus (addr_base_b, segment_length_b);
|
||||
if (tree_int_cst_compare (DR_STEP (dr_b.dr), size_zero_node) < 0)
|
||||
{
|
||||
tree unit_size = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr_b.dr)));
|
||||
seg_b_min = fold_build_pointer_plus (seg_b_max, unit_size);
|
||||
seg_b_max = fold_build_pointer_plus (addr_base_b, unit_size);
|
||||
}
|
||||
*cond_expr
|
||||
= fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
|
||||
fold_build2 (LE_EXPR, boolean_type_node, seg_a_max, seg_b_min),
|
||||
fold_build2 (LE_EXPR, boolean_type_node, seg_b_max, seg_a_min));
|
||||
}
|
||||
|
||||
/* Function vect_create_cond_for_alias_checks.
|
||||
|
||||
Create a conditional expression that represents the run-time checks for
|
||||
@ -2257,36 +2069,12 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
|
||||
{
|
||||
vec<dr_with_seg_len_pair_t> comp_alias_ddrs =
|
||||
LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo);
|
||||
tree part_cond_expr;
|
||||
|
||||
if (comp_alias_ddrs.is_empty ())
|
||||
return;
|
||||
|
||||
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
|
||||
for (size_t i = 0, s = comp_alias_ddrs.length (); i < s; ++i)
|
||||
{
|
||||
const dr_with_seg_len& dr_a = comp_alias_ddrs[i].first;
|
||||
const dr_with_seg_len& dr_b = comp_alias_ddrs[i].second;
|
||||
|
||||
if (dump_enabled_p ())
|
||||
{
|
||||
dump_printf_loc (MSG_NOTE, vect_location,
|
||||
"create runtime check for data references ");
|
||||
dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a.dr));
|
||||
dump_printf (MSG_NOTE, " and ");
|
||||
dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b.dr));
|
||||
dump_printf (MSG_NOTE, "\n");
|
||||
}
|
||||
|
||||
/* Create condition expression for each pair data references. */
|
||||
create_intersect_range_checks (loop, &part_cond_expr, dr_a, dr_b);
|
||||
if (*cond_expr)
|
||||
*cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
|
||||
*cond_expr, part_cond_expr);
|
||||
else
|
||||
*cond_expr = part_cond_expr;
|
||||
}
|
||||
|
||||
create_runtime_alias_checks (LOOP_VINFO_LOOP (loop_vinfo),
|
||||
&comp_alias_ddrs, cond_expr);
|
||||
if (dump_enabled_p ())
|
||||
dump_printf_loc (MSG_NOTE, vect_location,
|
||||
"created %u versioning for alias checks.\n",
|
||||
|
Loading…
Reference in New Issue
Block a user