tree-vectorizer.h (struct dr_with_seg_len): Remove class member OFFSET.

* tree-vectorizer.h (struct dr_with_seg_len): Remove class
	member OFFSET.
	* tree-vect-data-refs.c (operator ==): Handle DR_OFFSET directly,
	rather than OFFSET.
	(comp_dr_with_seg_len_pair): Ditto.
	(vect_prune_runtime_alias_test_list): Ditto.  Also Canonicalize
	struct dr_with_seg_len_pair against DR_OFFSET.
	* tree-vect-loop-manip.c (vect_create_cond_for_alias_checks): Handle
	DR_OFFSET directly.

	* gcc.dg/vect/vect-alias-check-1.c: New test.

From-SVN: r237549
This commit is contained in:
Bin Cheng 2016-06-17 09:05:05 +00:00 committed by Bin Cheng
parent 7c80a459b9
commit 97816be433
6 changed files with 80 additions and 39 deletions

View File

@ -1,3 +1,15 @@
2016-06-17 Bin Cheng <bin.cheng@arm.com>
* tree-vectorizer.h (struct dr_with_seg_len): Remove class
member OFFSET.
* tree-vect-data-refs.c (operator ==): Handle DR_OFFSET directly,
rather than OFFSET.
(comp_dr_with_seg_len_pair): Ditto.
(vect_prune_runtime_alias_test_list): Ditto. Also Canonicalize
struct dr_with_seg_len_pair against DR_OFFSET.
* tree-vect-loop-manip.c (vect_create_cond_for_alias_checks): Handle
DR_OFFSET directly.
2016-06-17 Szabolcs Nagy <szabolcs.nagy@arm.com>
* config/aarch64/geniterators.sh: Handle parenthesised conditions.

View File

@ -1,3 +1,7 @@
2016-06-17 Bin Cheng <bin.cheng@arm.com>
* gcc.dg/vect/vect-alias-check-1.c: New test.
2016-06-16 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
* gcc.target/avr/pr71151-1.c: New test.

View File

@ -0,0 +1,17 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_int } */
/* { dg-additional-options "-Ofast" } */
int b, c = 1;
int a[6][5] = { {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 1, 0, 0, 0} };
void
fn1 ()
{
int d;
for (b = 0; b < 5; b++)
for (d = 4; d; d--)
a[c + 1][b] = a[d + 1][d];
}
/* { dg-final { scan-tree-dump "improved number of alias checks from \[0-9\]* to 1" "vect" } } */

View File

@ -2851,7 +2851,8 @@ operator == (const dr_with_seg_len& d1,
{
return operand_equal_p (DR_BASE_ADDRESS (d1.dr),
DR_BASE_ADDRESS (d2.dr), 0)
&& compare_tree (d1.offset, d2.offset) == 0
&& compare_tree (DR_OFFSET (d1.dr), DR_OFFSET (d2.dr)) == 0
&& compare_tree (DR_INIT (d1.dr), DR_INIT (d2.dr)) == 0
&& compare_tree (d1.seg_len, d2.seg_len) == 0;
}
@ -2861,15 +2862,12 @@ operator == (const dr_with_seg_len& d1,
so that we can combine aliasing checks in one scan. */
static int
comp_dr_with_seg_len_pair (const void *p1_, const void *p2_)
comp_dr_with_seg_len_pair (const void *pa_, const void *pb_)
{
const dr_with_seg_len_pair_t* p1 = (const dr_with_seg_len_pair_t *) p1_;
const dr_with_seg_len_pair_t* p2 = (const dr_with_seg_len_pair_t *) p2_;
const dr_with_seg_len &p11 = p1->first,
&p12 = p1->second,
&p21 = p2->first,
&p22 = p2->second;
const dr_with_seg_len_pair_t* pa = (const dr_with_seg_len_pair_t *) pa_;
const dr_with_seg_len_pair_t* pb = (const dr_with_seg_len_pair_t *) pb_;
const dr_with_seg_len &a1 = pa->first, &a2 = pa->second;
const dr_with_seg_len &b1 = pb->first, &b2 = pb->second;
/* For DR pairs (a, b) and (c, d), we only consider to merge the alias checks
if a and c have the same basic address snd step, and b and d have the same
@ -2877,19 +2875,23 @@ comp_dr_with_seg_len_pair (const void *p1_, const void *p2_)
and step, we don't care the order of those two pairs after sorting. */
int comp_res;
if ((comp_res = compare_tree (DR_BASE_ADDRESS (p11.dr),
DR_BASE_ADDRESS (p21.dr))) != 0)
if ((comp_res = compare_tree (DR_BASE_ADDRESS (a1.dr),
DR_BASE_ADDRESS (b1.dr))) != 0)
return comp_res;
if ((comp_res = compare_tree (DR_BASE_ADDRESS (p12.dr),
DR_BASE_ADDRESS (p22.dr))) != 0)
if ((comp_res = compare_tree (DR_BASE_ADDRESS (a2.dr),
DR_BASE_ADDRESS (b2.dr))) != 0)
return comp_res;
if ((comp_res = compare_tree (DR_STEP (p11.dr), DR_STEP (p21.dr))) != 0)
if ((comp_res = compare_tree (DR_STEP (a1.dr), DR_STEP (b1.dr))) != 0)
return comp_res;
if ((comp_res = compare_tree (DR_STEP (p12.dr), DR_STEP (p22.dr))) != 0)
if ((comp_res = compare_tree (DR_STEP (a2.dr), DR_STEP (b2.dr))) != 0)
return comp_res;
if ((comp_res = compare_tree (p11.offset, p21.offset)) != 0)
if ((comp_res = compare_tree (DR_OFFSET (a1.dr), DR_OFFSET (b1.dr))) != 0)
return comp_res;
if ((comp_res = compare_tree (p12.offset, p22.offset)) != 0)
if ((comp_res = compare_tree (DR_INIT (a1.dr), DR_INIT (b1.dr))) != 0)
return comp_res;
if ((comp_res = compare_tree (DR_OFFSET (a2.dr), DR_OFFSET (b2.dr))) != 0)
return comp_res;
if ((comp_res = compare_tree (DR_INIT (a2.dr), DR_INIT (b2.dr))) != 0)
return comp_res;
return 0;
@ -2992,6 +2994,7 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
/* First, we collect all data ref pairs for aliasing checks. */
FOR_EACH_VEC_ELT (may_alias_ddrs, i, ddr)
{
int comp_res;
struct data_reference *dr_a, *dr_b;
gimple *dr_group_first_a, *dr_group_first_b;
tree segment_length_a, segment_length_b;
@ -3026,7 +3029,11 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
(dr_with_seg_len (dr_a, segment_length_a),
dr_with_seg_len (dr_b, segment_length_b));
if (compare_tree (DR_BASE_ADDRESS (dr_a), DR_BASE_ADDRESS (dr_b)) > 0)
/* Canonicalize pairs by sorting the two DR members. */
comp_res = compare_tree (DR_BASE_ADDRESS (dr_a), DR_BASE_ADDRESS (dr_b));
if (comp_res > 0
|| (comp_res == 0
&& compare_tree (DR_OFFSET (dr_a), DR_OFFSET (dr_b)) > 0))
std::swap (dr_with_seg_len_pair.first, dr_with_seg_len_pair.second);
comp_alias_ddrs.safe_push (dr_with_seg_len_pair);
@ -3082,21 +3089,21 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
}
if (!operand_equal_p (DR_BASE_ADDRESS (dr_a1->dr),
DR_BASE_ADDRESS (dr_a2->dr),
0)
|| !tree_fits_shwi_p (dr_a1->offset)
|| !tree_fits_shwi_p (dr_a2->offset))
DR_BASE_ADDRESS (dr_a2->dr), 0)
|| !operand_equal_p (DR_OFFSET (dr_a1->dr),
DR_OFFSET (dr_a2->dr), 0)
|| !tree_fits_shwi_p (DR_INIT (dr_a1->dr))
|| !tree_fits_shwi_p (DR_INIT (dr_a2->dr)))
continue;
/* Make sure dr_a1 starts left of dr_a2. */
if (tree_int_cst_lt (dr_a2->offset, dr_a1->offset))
if (tree_int_cst_lt (DR_INIT (dr_a2->dr), DR_INIT (dr_a1->dr)))
std::swap (*dr_a1, *dr_a2);
unsigned HOST_WIDE_INT diff
= tree_to_shwi (dr_a2->offset) - tree_to_shwi (dr_a1->offset);
bool do_remove = false;
unsigned HOST_WIDE_INT diff
= (tree_to_shwi (DR_INIT (dr_a2->dr))
- tree_to_shwi (DR_INIT (dr_a1->dr)));
/* If the left segment does not extend beyond the start of the
right segment the new segment length is that of the right
@ -3124,7 +3131,7 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
DIFF - SEGMENT_LENGTH_A < SEGMENT_LENGTH_B
where DIFF = DR_A2->OFFSET - DR_A1->OFFSET. However,
where DIFF = DR_A2_INIT - DR_A1_INIT. However,
SEGMENT_LENGTH_A or SEGMENT_LENGTH_B may not be constant so we
have to make a best estimation. We can get the minimum value
of SEGMENT_LENGTH_B as a constant, represented by MIN_SEG_LEN_B,

View File

@ -2238,11 +2238,16 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
const dr_with_seg_len& dr_b = comp_alias_ddrs[i].second;
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);
tree addr_base_a
= fold_build_pointer_plus (DR_BASE_ADDRESS (dr_a.dr), dr_a.offset);
tree addr_base_b
= fold_build_pointer_plus (DR_BASE_ADDRESS (dr_b.dr), dr_b.offset);
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);
if (dump_enabled_p ())
{

View File

@ -146,19 +146,15 @@ typedef struct _slp_instance {
/* This struct is used to store the information of a data reference,
including the data ref itself, the access offset (calculated by summing its
offset and init) and the segment length for aliasing checks.
This is used to merge alias checks. */
including the data ref itself and the segment length for aliasing
checks. This is used to merge alias checks. */
struct dr_with_seg_len
{
dr_with_seg_len (data_reference_p d, tree len)
: dr (d),
offset (size_binop (PLUS_EXPR, DR_OFFSET (d), DR_INIT (d))),
seg_len (len) {}
: dr (d), seg_len (len) {}
data_reference_p dr;
tree offset;
tree seg_len;
};