Commit 97816be4 by Bin Cheng Committed by Bin Cheng

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
parent 7c80a459
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> 2016-06-17 Szabolcs Nagy <szabolcs.nagy@arm.com>
* config/aarch64/geniterators.sh: Handle parenthesised conditions. * config/aarch64/geniterators.sh: Handle parenthesised conditions.
......
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> 2016-06-16 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
* gcc.target/avr/pr71151-1.c: New test. * gcc.target/avr/pr71151-1.c: New test.
......
/* { 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" } } */
...@@ -2851,7 +2851,8 @@ operator == (const dr_with_seg_len& d1, ...@@ -2851,7 +2851,8 @@ operator == (const dr_with_seg_len& d1,
{ {
return operand_equal_p (DR_BASE_ADDRESS (d1.dr), return operand_equal_p (DR_BASE_ADDRESS (d1.dr),
DR_BASE_ADDRESS (d2.dr), 0) 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; && compare_tree (d1.seg_len, d2.seg_len) == 0;
} }
...@@ -2861,15 +2862,12 @@ operator == (const dr_with_seg_len& d1, ...@@ -2861,15 +2862,12 @@ operator == (const dr_with_seg_len& d1,
so that we can combine aliasing checks in one scan. */ so that we can combine aliasing checks in one scan. */
static int 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* pa = (const dr_with_seg_len_pair_t *) pa_;
const dr_with_seg_len_pair_t* p2 = (const dr_with_seg_len_pair_t *) p2_; 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 &p11 = p1->first, const dr_with_seg_len &b1 = pb->first, &b2 = pb->second;
&p12 = p1->second,
&p21 = p2->first,
&p22 = p2->second;
/* For DR pairs (a, b) and (c, d), we only consider to merge the alias checks /* 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 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_) ...@@ -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. */ and step, we don't care the order of those two pairs after sorting. */
int comp_res; int comp_res;
if ((comp_res = compare_tree (DR_BASE_ADDRESS (p11.dr), if ((comp_res = compare_tree (DR_BASE_ADDRESS (a1.dr),
DR_BASE_ADDRESS (p21.dr))) != 0) DR_BASE_ADDRESS (b1.dr))) != 0)
return comp_res;
if ((comp_res = compare_tree (DR_BASE_ADDRESS (a2.dr),
DR_BASE_ADDRESS (b2.dr))) != 0)
return comp_res; return comp_res;
if ((comp_res = compare_tree (DR_BASE_ADDRESS (p12.dr), if ((comp_res = compare_tree (DR_STEP (a1.dr), DR_STEP (b1.dr))) != 0)
DR_BASE_ADDRESS (p22.dr))) != 0)
return comp_res; return comp_res;
if ((comp_res = compare_tree (DR_STEP (p11.dr), DR_STEP (p21.dr))) != 0) if ((comp_res = compare_tree (DR_STEP (a2.dr), DR_STEP (b2.dr))) != 0)
return comp_res; return comp_res;
if ((comp_res = compare_tree (DR_STEP (p12.dr), DR_STEP (p22.dr))) != 0) if ((comp_res = compare_tree (DR_OFFSET (a1.dr), DR_OFFSET (b1.dr))) != 0)
return comp_res; return comp_res;
if ((comp_res = compare_tree (p11.offset, p21.offset)) != 0) if ((comp_res = compare_tree (DR_INIT (a1.dr), DR_INIT (b1.dr))) != 0)
return comp_res; return comp_res;
if ((comp_res = compare_tree (p12.offset, p22.offset)) != 0) 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 comp_res;
return 0; return 0;
...@@ -2992,6 +2994,7 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo) ...@@ -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. */ /* First, we collect all data ref pairs for aliasing checks. */
FOR_EACH_VEC_ELT (may_alias_ddrs, i, ddr) FOR_EACH_VEC_ELT (may_alias_ddrs, i, ddr)
{ {
int comp_res;
struct data_reference *dr_a, *dr_b; struct data_reference *dr_a, *dr_b;
gimple *dr_group_first_a, *dr_group_first_b; gimple *dr_group_first_a, *dr_group_first_b;
tree segment_length_a, segment_length_b; tree segment_length_a, segment_length_b;
...@@ -3026,7 +3029,11 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo) ...@@ -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_a, segment_length_a),
dr_with_seg_len (dr_b, segment_length_b)); 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); std::swap (dr_with_seg_len_pair.first, dr_with_seg_len_pair.second);
comp_alias_ddrs.safe_push (dr_with_seg_len_pair); 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) ...@@ -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), if (!operand_equal_p (DR_BASE_ADDRESS (dr_a1->dr),
DR_BASE_ADDRESS (dr_a2->dr), DR_BASE_ADDRESS (dr_a2->dr), 0)
0) || !operand_equal_p (DR_OFFSET (dr_a1->dr),
|| !tree_fits_shwi_p (dr_a1->offset) DR_OFFSET (dr_a2->dr), 0)
|| !tree_fits_shwi_p (dr_a2->offset)) || !tree_fits_shwi_p (DR_INIT (dr_a1->dr))
|| !tree_fits_shwi_p (DR_INIT (dr_a2->dr)))
continue; continue;
/* Make sure dr_a1 starts left of dr_a2. */ /* 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); 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; 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 /* If the left segment does not extend beyond the start of the
right segment the new segment length is that of the right 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) ...@@ -3124,7 +3131,7 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
DIFF - SEGMENT_LENGTH_A < SEGMENT_LENGTH_B 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 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 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, of SEGMENT_LENGTH_B as a constant, represented by MIN_SEG_LEN_B,
......
...@@ -2238,11 +2238,16 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr) ...@@ -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; const dr_with_seg_len& dr_b = comp_alias_ddrs[i].second;
tree segment_length_a = dr_a.seg_len; tree segment_length_a = dr_a.seg_len;
tree segment_length_b = dr_b.seg_len; tree segment_length_b = dr_b.seg_len;
tree addr_base_a = DR_BASE_ADDRESS (dr_a.dr);
tree addr_base_a tree addr_base_b = DR_BASE_ADDRESS (dr_b.dr);
= fold_build_pointer_plus (DR_BASE_ADDRESS (dr_a.dr), dr_a.offset); tree offset_a = DR_OFFSET (dr_a.dr), offset_b = DR_OFFSET (dr_b.dr);
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 ()) if (dump_enabled_p ())
{ {
......
...@@ -146,19 +146,15 @@ typedef struct _slp_instance { ...@@ -146,19 +146,15 @@ typedef struct _slp_instance {
/* This struct is used to store the information of a data reference, /* This struct is used to store the information of a data reference,
including the data ref itself, the access offset (calculated by summing its including the data ref itself and the segment length for aliasing
offset and init) and the segment length for aliasing checks. checks. This is used to merge alias checks. */
This is used to merge alias checks. */
struct dr_with_seg_len struct dr_with_seg_len
{ {
dr_with_seg_len (data_reference_p d, tree len) dr_with_seg_len (data_reference_p d, tree len)
: dr (d), : dr (d), seg_len (len) {}
offset (size_binop (PLUS_EXPR, DR_OFFSET (d), DR_INIT (d))),
seg_len (len) {}
data_reference_p dr; data_reference_p dr;
tree offset;
tree seg_len; tree seg_len;
}; };
......
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