Commit 93bdc3ed by Cong Hou Committed by Cong Hou

tree-vectorizer.h (struct dr_with_seg_len): Remove the base address field as it…

tree-vectorizer.h (struct dr_with_seg_len): Remove the base address field as it can be obtained from dr.

2013-11-14  Cong Hou  <congh@google.com>

    * tree-vectorizer.h (struct dr_with_seg_len): Remove the base
    address field as it can be obtained from dr.  Rename the struct.
    * tree-vect-data-refs.c (comp_dr_with_seg_len_pair): Consider
    steps of data references during sort.
    (vect_prune_runtime_alias_test_list): Adjust with the change to
    struct dr_with_seg_len.
    * tree-vect-loop-manip.c (vect_create_cond_for_alias_checks):
    Adjust with the change to struct dr_with_seg_len.

2013-11-14  Cong Hou  <congh@google.com>

    * gcc.dg/vect/vect-alias-check.c: Update.

From-SVN: r204822
parent 5e94175f
2013-11-14 Cong Hou <congh@google.com>
* tree-vectorizer.h (struct dr_with_seg_len): Remove the base
address field as it can be obtained from dr. Rename the struct.
* tree-vect-data-refs.c (comp_dr_with_seg_len_pair): Consider
steps of data references during sort.
(vect_prune_runtime_alias_test_list): Adjust with the change to
struct dr_with_seg_len.
* tree-vect-loop-manip.c (vect_create_cond_for_alias_checks):
Adjust with the change to struct dr_with_seg_len.
2013-11-14 Jeff Law <law@redhat.com>
PR middle-end/59127
2013-11-14 Cong Hou <congh@google.com>
* gcc.dg/vect/vect-alias-check.c: Update.
2013-11-14 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/57887
......
/* { dg-require-effective-target vect_int } */
/* { dg-do compile } */
/* { dg-options "-O2 -ftree-vectorize --param=vect-max-version-for-alias-checks=2 -fdump-tree-vect-details" } */
/* { dg-additional-options "--param=vect-max-version-for-alias-checks=2" } */
/* A test case showing three potential alias checks between
a[i] and b[i], b[i+7], b[i+14]. With alias checks merging
enabled, those tree checks can be merged into one, and the
loop will be vectorized with vect-max-version-for-alias-checks=2. */
/* A test case showing four potential alias checks between a[i] and b[0], b[1],
b[i+1] and b[i+2]. With alias check merging enabled, those four checks
can be merged into two, and the loop will be vectorized with
vect-max-version-for-alias-checks=2. */
void foo (int *a, int *b)
{
int i;
for (i = 0; i < 1000; ++i)
a[i] = b[i] + b[i+7] + b[i+14];
a[i] = b[0] + b[1] + b[i+1] + b[i+2];
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
......
......@@ -2623,7 +2623,7 @@ vect_analyze_data_ref_accesses (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
}
/* Operator == between two dr_addr_with_seg_len objects.
/* Operator == between two dr_with_seg_len objects.
This equality operator is used to make sure two data refs
are the same one so that we will consider to combine the
......@@ -2631,62 +2631,51 @@ vect_analyze_data_ref_accesses (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
refs. */
static bool
operator == (const dr_addr_with_seg_len& d1,
const dr_addr_with_seg_len& d2)
operator == (const dr_with_seg_len& d1,
const dr_with_seg_len& d2)
{
return operand_equal_p (d1.basic_addr, d2.basic_addr, 0)
return operand_equal_p (DR_BASE_ADDRESS (d1.dr),
DR_BASE_ADDRESS (d2.dr), 0)
&& compare_tree (d1.offset, d2.offset) == 0
&& compare_tree (d1.seg_len, d2.seg_len) == 0;
}
/* Function comp_dr_addr_with_seg_len_pair.
/* Function comp_dr_with_seg_len_pair.
Comparison function for sorting objects of dr_addr_with_seg_len_pair_t
Comparison function for sorting objects of dr_with_seg_len_pair_t
so that we can combine aliasing checks in one scan. */
static int
comp_dr_addr_with_seg_len_pair (const void *p1_, const void *p2_)
comp_dr_with_seg_len_pair (const void *p1_, const void *p2_)
{
const dr_addr_with_seg_len_pair_t* p1 =
(const dr_addr_with_seg_len_pair_t *) p1_;
const dr_addr_with_seg_len_pair_t* p2 =
(const dr_addr_with_seg_len_pair_t *) p2_;
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_addr_with_seg_len &p11 = p1->first,
const dr_with_seg_len &p11 = p1->first,
&p12 = p1->second,
&p21 = p2->first,
&p22 = p2->second;
int comp_res = compare_tree (p11.basic_addr, p21.basic_addr);
if (comp_res != 0)
return comp_res;
/* 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
address and step. Therefore, if any a&c or b&d don't have the same address
and step, we don't care the order of those two pairs after sorting. */
int comp_res;
comp_res = compare_tree (p12.basic_addr, p22.basic_addr);
if (comp_res != 0)
if ((comp_res = compare_tree (DR_BASE_ADDRESS (p11.dr),
DR_BASE_ADDRESS (p21.dr))) != 0)
return comp_res;
if (TREE_CODE (p11.offset) != INTEGER_CST
|| TREE_CODE (p21.offset) != INTEGER_CST)
{
comp_res = compare_tree (p11.offset, p21.offset);
if (comp_res != 0)
if ((comp_res = compare_tree (DR_BASE_ADDRESS (p12.dr),
DR_BASE_ADDRESS (p22.dr))) != 0)
return comp_res;
}
else if (tree_int_cst_compare (p11.offset, p21.offset) < 0)
return -1;
else if (tree_int_cst_compare (p11.offset, p21.offset) > 0)
return 1;
if (TREE_CODE (p12.offset) != INTEGER_CST
|| TREE_CODE (p22.offset) != INTEGER_CST)
{
comp_res = compare_tree (p12.offset, p22.offset);
if (comp_res != 0)
if ((comp_res = compare_tree (DR_STEP (p11.dr), DR_STEP (p21.dr))) != 0)
return comp_res;
if ((comp_res = compare_tree (DR_STEP (p12.dr), DR_STEP (p22.dr))) != 0)
return comp_res;
if ((comp_res = compare_tree (p11.offset, p21.offset)) != 0)
return comp_res;
if ((comp_res = compare_tree (p12.offset, p22.offset)) != 0)
return comp_res;
}
else if (tree_int_cst_compare (p12.offset, p22.offset) < 0)
return -1;
else if (tree_int_cst_compare (p12.offset, p22.offset) > 0)
return 1;
return 0;
}
......@@ -2747,7 +2736,7 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
{
vec<ddr_p> may_alias_ddrs =
LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo);
vec<dr_addr_with_seg_len_pair_t>& comp_alias_ddrs =
vec<dr_with_seg_len_pair_t>& comp_alias_ddrs =
LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo);
int vect_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
tree scalar_loop_iters = LOOP_VINFO_NITERS (loop_vinfo);
......@@ -2826,18 +2815,11 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
segment_length_a = vect_vfa_segment_size (dr_a, length_factor);
segment_length_b = vect_vfa_segment_size (dr_b, length_factor);
dr_addr_with_seg_len_pair_t dr_with_seg_len_pair
(dr_addr_with_seg_len
(dr_a, DR_BASE_ADDRESS (dr_a),
size_binop (PLUS_EXPR, DR_OFFSET (dr_a), DR_INIT (dr_a)),
segment_length_a),
dr_addr_with_seg_len
(dr_b, DR_BASE_ADDRESS (dr_b),
size_binop (PLUS_EXPR, DR_OFFSET (dr_b), DR_INIT (dr_b)),
segment_length_b));
if (compare_tree (dr_with_seg_len_pair.first.basic_addr,
dr_with_seg_len_pair.second.basic_addr) > 0)
dr_with_seg_len_pair_t dr_with_seg_len_pair
(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)
swap (dr_with_seg_len_pair.first, dr_with_seg_len_pair.second);
comp_alias_ddrs.safe_push (dr_with_seg_len_pair);
......@@ -2845,14 +2827,14 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
/* Second, we sort the collected data ref pairs so that we can scan
them once to combine all possible aliasing checks. */
comp_alias_ddrs.qsort (comp_dr_addr_with_seg_len_pair);
comp_alias_ddrs.qsort (comp_dr_with_seg_len_pair);
/* Third, we scan the sorted dr pairs and check if we can combine
alias checks of two neighbouring dr pairs. */
for (size_t i = 1; i < comp_alias_ddrs.length (); ++i)
{
/* Deal with two ddrs (dr_a1, dr_b1) and (dr_a2, dr_b2). */
dr_addr_with_seg_len *dr_a1 = &comp_alias_ddrs[i-1].first,
dr_with_seg_len *dr_a1 = &comp_alias_ddrs[i-1].first,
*dr_b1 = &comp_alias_ddrs[i-1].second,
*dr_a2 = &comp_alias_ddrs[i].first,
*dr_b2 = &comp_alias_ddrs[i].second;
......@@ -2892,7 +2874,9 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
swap (dr_a2, dr_b2);
}
if (!operand_equal_p (dr_a1->basic_addr, dr_a2->basic_addr, 0)
if (!operand_equal_p (DR_BASE_ADDRESS (dr_a1->dr),
DR_BASE_ADDRESS (dr_a2->dr),
0)
|| !host_integerp (dr_a1->offset, 0)
|| !host_integerp (dr_a2->offset, 0))
continue;
......
......@@ -2245,7 +2245,7 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
void
vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
{
vec<dr_addr_with_seg_len_pair_t> comp_alias_ddrs =
vec<dr_with_seg_len_pair_t> comp_alias_ddrs =
LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo);
tree part_cond_expr;
......@@ -2263,15 +2263,15 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
for (size_t i = 0, s = comp_alias_ddrs.length (); i < s; ++i)
{
const dr_addr_with_seg_len& dr_a = comp_alias_ddrs[i].first;
const dr_addr_with_seg_len& dr_b = comp_alias_ddrs[i].second;
const dr_with_seg_len& dr_a = comp_alias_ddrs[i].first;
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
= fold_build_pointer_plus (dr_a.basic_addr, dr_a.offset);
= fold_build_pointer_plus (DR_BASE_ADDRESS (dr_a.dr), dr_a.offset);
tree addr_base_b
= fold_build_pointer_plus (dr_b.basic_addr, dr_b.offset);
= fold_build_pointer_plus (DR_BASE_ADDRESS (dr_b.dr), dr_b.offset);
if (dump_enabled_p ())
{
......
......@@ -176,32 +176,33 @@ typedef struct _slp_oprnd_info
/* This struct is used to store the information of a data reference,
including the data ref itself, its basic address, the access offset
and the segment length for aliasing checks. This is used to generate
alias checks. */
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. */
struct dr_addr_with_seg_len
struct dr_with_seg_len
{
dr_addr_with_seg_len (data_reference* d, tree addr, tree off, tree len)
: dr (d), basic_addr (addr), offset (off), seg_len (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) {}
data_reference *dr;
tree basic_addr;
data_reference_p dr;
tree offset;
tree seg_len;
};
/* This struct contains two dr_addr_with_seg_len objects with aliasing data
/* This struct contains two dr_with_seg_len objects with aliasing data
refs. Two comparisons are generated from them. */
struct dr_addr_with_seg_len_pair_t
struct dr_with_seg_len_pair_t
{
dr_addr_with_seg_len_pair_t (const dr_addr_with_seg_len& d1,
const dr_addr_with_seg_len& d2)
dr_with_seg_len_pair_t (const dr_with_seg_len& d1,
const dr_with_seg_len& d2)
: first (d1), second (d2) {}
dr_addr_with_seg_len first;
dr_addr_with_seg_len second;
dr_with_seg_len first;
dr_with_seg_len second;
};
......@@ -306,7 +307,7 @@ typedef struct _loop_vec_info {
/* Data Dependence Relations defining address ranges together with segment
lengths from which the run-time aliasing check is built. */
vec<dr_addr_with_seg_len_pair_t> comp_alias_ddrs;
vec<dr_with_seg_len_pair_t> comp_alias_ddrs;
/* Statements in the loop that have data references that are candidates for a
runtime (loop versioning) misalignment check. */
......
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