Commit a05a89fa by Cong Hou Committed by Cong Hou

re PR tree-optimization/56764 (vect_prune_runtime_alias_test_list not smart enough)

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

	PR tree-optimization/56764
	* tree-vect-loop-manip.c (vect_create_cond_for_alias_checks):
  	Combine alias checks if it is possible to amortize the runtime
  	overhead.  Return the number of alias checks after merging.
  	* tree-vect-data-refs.c (vect_prune_runtime_alias_test_list):
    	Use the function vect_create_cond_for_alias_checks () to check
    	the number of alias checks.

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

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

From-SVN: r204538
parent 6d0b7105
2013-11-07 Cong Hou <congh@google.com>
PR tree-optimization/56764
* tree-vect-loop-manip.c (vect_create_cond_for_alias_checks):
Combine alias checks if it is possible to amortize the runtime
overhead. Return the number of alias checks after merging.
* tree-vect-data-refs.c (vect_prune_runtime_alias_test_list):
Use the function vect_create_cond_for_alias_checks () to check
the number of alias checks.
2013-11-07 Jeff Law <law@redhat.com> 2013-11-07 Jeff Law <law@redhat.com>
* varpool.c (ctor_for_folding): Fix typo in comment. * varpool.c (ctor_for_folding): Fix typo in comment.
2013-11-07 Cong Hou <congh@google.com>
* gcc.dg/vect/vect-alias-check.c: New.
2013-11-07 Jakub Jelinek <jakub@redhat.com> 2013-11-07 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/tree-ssa/loop-39.c: New test. * gcc.dg/tree-ssa/loop-39.c: New test.
......
/* { 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" } */
/* 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. */
void foo (int *a, int *b)
{
int i;
for (i = 0; i < 1000; ++i)
a[i] = b[i] + b[i+7] + b[i+14];
}
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
...@@ -2219,44 +2219,6 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo, ...@@ -2219,44 +2219,6 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo,
*cond_expr = part_cond_expr; *cond_expr = part_cond_expr;
} }
/* Function vect_vfa_segment_size.
Create an expression that computes the size of segment
that will be accessed for a data reference. The functions takes into
account that realignment loads may access one more vector.
Input:
DR: The data reference.
LENGTH_FACTOR: segment length to consider.
Return an expression whose value is the size of segment which will be
accessed by DR. */
static tree
vect_vfa_segment_size (struct data_reference *dr, tree length_factor)
{
tree segment_length;
if (integer_zerop (DR_STEP (dr)))
segment_length = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
else
segment_length = size_binop (MULT_EXPR,
fold_convert (sizetype, DR_STEP (dr)),
fold_convert (sizetype, length_factor));
if (vect_supportable_dr_alignment (dr, false)
== dr_explicit_realign_optimized)
{
tree vector_size = TYPE_SIZE_UNIT
(STMT_VINFO_VECTYPE (vinfo_for_stmt (DR_STMT (dr))));
segment_length = size_binop (PLUS_EXPR, segment_length, vector_size);
}
return segment_length;
}
/* Function vect_create_cond_for_alias_checks. /* Function vect_create_cond_for_alias_checks.
Create a conditional expression that represents the run-time checks for Create a conditional expression that represents the run-time checks for
...@@ -2265,28 +2227,24 @@ vect_vfa_segment_size (struct data_reference *dr, tree length_factor) ...@@ -2265,28 +2227,24 @@ vect_vfa_segment_size (struct data_reference *dr, tree length_factor)
Input: Input:
COND_EXPR - input conditional expression. New conditions will be chained COND_EXPR - input conditional expression. New conditions will be chained
with logical AND operation. with logical AND operation. If it is NULL, then the function
is used to return the number of alias checks.
LOOP_VINFO - field LOOP_VINFO_MAY_ALIAS_STMTS contains the list of ddrs LOOP_VINFO - field LOOP_VINFO_MAY_ALIAS_STMTS contains the list of ddrs
to be checked. to be checked.
Output: Output:
COND_EXPR - conditional expression. COND_EXPR - conditional expression.
The returned value is the conditional expression to be used in the if 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. statement that controls which version of the loop gets executed at runtime.
*/ */
static void void
vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr) vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
{ {
vec<ddr_p> may_alias_ddrs = vec<dr_addr_with_seg_len_pair_t> comp_alias_ddrs =
LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo); LOOP_VINFO_COMP_ALIAS_DDRS (loop_vinfo);
int vect_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo); tree part_cond_expr;
tree scalar_loop_iters = LOOP_VINFO_NITERS (loop_vinfo);
ddr_p ddr;
unsigned int i;
tree part_cond_expr, length_factor;
/* Create expression /* Create expression
((store_ptr_0 + store_segment_length_0) <= load_ptr_0) ((store_ptr_0 + store_segment_length_0) <= load_ptr_0)
...@@ -2297,70 +2255,39 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr) ...@@ -2297,70 +2255,39 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
((store_ptr_n + store_segment_length_n) <= load_ptr_n) ((store_ptr_n + store_segment_length_n) <= load_ptr_n)
|| (load_ptr_n + load_segment_length_n) <= store_ptr_n)) */ || (load_ptr_n + load_segment_length_n) <= store_ptr_n)) */
if (may_alias_ddrs.is_empty ()) if (comp_alias_ddrs.is_empty ())
return; return;
FOR_EACH_VEC_ELT (may_alias_ddrs, i, ddr) for (size_t i = 0, s = comp_alias_ddrs.length (); i < s; ++i)
{ {
struct data_reference *dr_a, *dr_b; const dr_addr_with_seg_len& dr_a = comp_alias_ddrs[i].first;
gimple dr_group_first_a, dr_group_first_b; const dr_addr_with_seg_len& dr_b = comp_alias_ddrs[i].second;
tree addr_base_a, addr_base_b; tree segment_length_a = dr_a.seg_len;
tree segment_length_a, segment_length_b; tree segment_length_b = dr_b.seg_len;
gimple stmt_a, stmt_b;
tree seg_a_min, seg_a_max, seg_b_min, seg_b_max;
dr_a = DDR_A (ddr);
stmt_a = DR_STMT (DDR_A (ddr));
dr_group_first_a = GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_a));
if (dr_group_first_a)
{
stmt_a = dr_group_first_a;
dr_a = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_a));
}
dr_b = DDR_B (ddr);
stmt_b = DR_STMT (DDR_B (ddr));
dr_group_first_b = GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt_b));
if (dr_group_first_b)
{
stmt_b = dr_group_first_b;
dr_b = STMT_VINFO_DATA_REF (vinfo_for_stmt (stmt_b));
}
addr_base_a tree addr_base_a
= fold_build_pointer_plus (DR_BASE_ADDRESS (dr_a), = fold_build_pointer_plus (dr_a.basic_addr, dr_a.offset);
size_binop (PLUS_EXPR, DR_OFFSET (dr_a), tree addr_base_b
DR_INIT (dr_a))); = fold_build_pointer_plus (dr_b.basic_addr, dr_b.offset);
addr_base_b
= fold_build_pointer_plus (DR_BASE_ADDRESS (dr_b),
size_binop (PLUS_EXPR, DR_OFFSET (dr_b),
DR_INIT (dr_b)));
if (!operand_equal_p (DR_STEP (dr_a), DR_STEP (dr_b), 0))
length_factor = scalar_loop_iters;
else
length_factor = size_int (vect_factor);
segment_length_a = vect_vfa_segment_size (dr_a, length_factor);
segment_length_b = vect_vfa_segment_size (dr_b, length_factor);
if (dump_enabled_p ()) if (dump_enabled_p ())
{ {
dump_printf_loc (MSG_NOTE, vect_location, dump_printf_loc (MSG_NOTE, vect_location,
"create runtime check for data references "); "create runtime check for data references ");
dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a)); dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_a.dr));
dump_printf (MSG_NOTE, " and "); dump_printf (MSG_NOTE, " and ");
dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b)); dump_generic_expr (MSG_NOTE, TDF_SLIM, DR_REF (dr_b.dr));
dump_printf (MSG_NOTE, "\n"); dump_printf (MSG_NOTE, "\n");
} }
seg_a_min = addr_base_a; tree seg_a_min = addr_base_a;
seg_a_max = fold_build_pointer_plus (addr_base_a, segment_length_a); tree seg_a_max = fold_build_pointer_plus (addr_base_a, segment_length_a);
if (tree_int_cst_compare (DR_STEP (dr_a), size_zero_node) < 0) if (tree_int_cst_compare (DR_STEP (dr_a.dr), size_zero_node) < 0)
seg_a_min = seg_a_max, seg_a_max = addr_base_a; seg_a_min = seg_a_max, seg_a_max = addr_base_a;
seg_b_min = addr_base_b; tree seg_b_min = addr_base_b;
seg_b_max = fold_build_pointer_plus (addr_base_b, segment_length_b); tree seg_b_max = fold_build_pointer_plus (addr_base_b, segment_length_b);
if (tree_int_cst_compare (DR_STEP (dr_b), size_zero_node) < 0) if (tree_int_cst_compare (DR_STEP (dr_b.dr), size_zero_node) < 0)
seg_b_min = seg_b_max, seg_b_max = addr_base_b; seg_b_min = seg_b_max, seg_b_max = addr_base_b;
part_cond_expr = part_cond_expr =
...@@ -2378,7 +2305,9 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr) ...@@ -2378,7 +2305,9 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, tree * cond_expr)
if (dump_enabled_p ()) if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, dump_printf_loc (MSG_NOTE, vect_location,
"created %u versioning for alias checks.\n", "created %u versioning for alias checks.\n",
may_alias_ddrs.length ()); comp_alias_ddrs.length ());
comp_alias_ddrs.release ();
} }
......
...@@ -175,6 +175,36 @@ typedef struct _slp_oprnd_info ...@@ -175,6 +175,36 @@ 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. */
struct dr_addr_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) {}
data_reference *dr;
tree basic_addr;
tree offset;
tree seg_len;
};
/* This struct contains two dr_addr_with_seg_len objects with aliasing data
refs. Two comparisons are generated from them. */
struct dr_addr_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)
: first (d1), second (d2) {}
dr_addr_with_seg_len first;
dr_addr_with_seg_len second;
};
typedef struct _vect_peel_info typedef struct _vect_peel_info
{ {
int npeel; int npeel;
...@@ -274,6 +304,10 @@ typedef struct _loop_vec_info { ...@@ -274,6 +304,10 @@ typedef struct _loop_vec_info {
for a run-time aliasing check. */ for a run-time aliasing check. */
vec<ddr_p> may_alias_ddrs; vec<ddr_p> may_alias_ddrs;
/* 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;
/* Statements in the loop that have data references that are candidates for a /* Statements in the loop that have data references that are candidates for a
runtime (loop versioning) misalignment check. */ runtime (loop versioning) misalignment check. */
vec<gimple> may_misalign_stmts; vec<gimple> may_misalign_stmts;
...@@ -336,6 +370,7 @@ typedef struct _loop_vec_info { ...@@ -336,6 +370,7 @@ typedef struct _loop_vec_info {
#define LOOP_VINFO_MAY_MISALIGN_STMTS(L) (L)->may_misalign_stmts #define LOOP_VINFO_MAY_MISALIGN_STMTS(L) (L)->may_misalign_stmts
#define LOOP_VINFO_LOC(L) (L)->loop_line_number #define LOOP_VINFO_LOC(L) (L)->loop_line_number
#define LOOP_VINFO_MAY_ALIAS_DDRS(L) (L)->may_alias_ddrs #define LOOP_VINFO_MAY_ALIAS_DDRS(L) (L)->may_alias_ddrs
#define LOOP_VINFO_COMP_ALIAS_DDRS(L) (L)->comp_alias_ddrs
#define LOOP_VINFO_GROUPED_STORES(L) (L)->grouped_stores #define LOOP_VINFO_GROUPED_STORES(L) (L)->grouped_stores
#define LOOP_VINFO_SLP_INSTANCES(L) (L)->slp_instances #define LOOP_VINFO_SLP_INSTANCES(L) (L)->slp_instances
#define LOOP_VINFO_SLP_UNROLLING_FACTOR(L) (L)->slp_unrolling_factor #define LOOP_VINFO_SLP_UNROLLING_FACTOR(L) (L)->slp_unrolling_factor
......
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