mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-18 23:51:08 +08:00
re PR tree-optimization/64746 (Loop with nested load/stores is not vectorized using aggressive if-conversion.)
gcc/ PR tree-optimization/64746 * tree-if-conv.c (mask_exists): New function. (predicate_mem_writes): Save created mask with given size for further use. (stmt_is_root_of_bool_pattern): Remove argument VAR and store to it. (ifcvt_repair_bool_pattern): Collect all statements that are root of bool pattern and use iterative algorithm to remove multiple uses of predicates, display number of required iterations. gcc/testsuite/ PR tree-optimization/64746 * gcc.target/i386/avx2-vect-aggressive-1.c: New test. From-SVN: r220248
This commit is contained in:
parent
d94e3e750d
commit
b8aa7083ec
@ -1,3 +1,14 @@
|
||||
2015-01-29 Yuri Rumyantsev <ysrumyan@gmail.com>
|
||||
|
||||
PR tree-optimization/64746
|
||||
* tree-if-conv.c (mask_exists): New function.
|
||||
(predicate_mem_writes): Save created mask with given size for further
|
||||
use.
|
||||
(stmt_is_root_of_bool_pattern): Remove argument VAR and store to it.
|
||||
(ifcvt_repair_bool_pattern): Collect all statements that are root
|
||||
of bool pattern and use iterative algorithm to remove multiple uses
|
||||
of predicates, display number of required iterations.
|
||||
|
||||
2015-01-29 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/64853
|
||||
|
@ -1,3 +1,8 @@
|
||||
2015-01-29 Yuri Rumyantsev <ysrumyan@gmail.com>
|
||||
|
||||
PR tree-optimization/64746
|
||||
* gcc.target/i386/avx2-vect-aggressive-1.c: New test.
|
||||
|
||||
2015-01-29 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/64853
|
||||
|
33
gcc/testsuite/gcc.target/i386/avx2-vect-aggressive-1.c
Normal file
33
gcc/testsuite/gcc.target/i386/avx2-vect-aggressive-1.c
Normal file
@ -0,0 +1,33 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-effective-target avx2 } */
|
||||
/* { dg-options "-mavx2 -O3 -fopenmp-simd -fdump-tree-vect-details" } */
|
||||
|
||||
#define N 256
|
||||
int a1[N], a2[N], a3[N], a4[N], a5[N], a6[N], a7[N];
|
||||
|
||||
void foo()
|
||||
{
|
||||
int x1, x2, x3;
|
||||
int i;
|
||||
#pragma omp simd safelen(8)
|
||||
for (i=0; i<N; i++)
|
||||
{
|
||||
x1 = a1[i] + a2 [i];
|
||||
if (x1 >= 0 && x1 != 3)
|
||||
{
|
||||
x2 = a3[i] - a1[i];
|
||||
if (x2 >= 0 && x2 != 4)
|
||||
{
|
||||
x3 = a4[i] + a5[i];
|
||||
if (x3 >= 0 && x3 != 5)
|
||||
{
|
||||
a6[i] = x1 - x2;
|
||||
a7[i] = x3 + x2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
|
||||
/* { dg-final { cleanup-tree-dump "vect" } } */
|
@ -1974,6 +1974,20 @@ insert_gimplified_predicates (loop_p loop, bool any_mask_load_store)
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper function for predicate_mem_writes. Returns index of existent
|
||||
mask if it was created for given SIZE and -1 otherwise. */
|
||||
|
||||
static int
|
||||
mask_exists (int size, vec<int> vec)
|
||||
{
|
||||
unsigned int ix;
|
||||
int v;
|
||||
FOR_EACH_VEC_ELT (vec, ix, v)
|
||||
if (v == size)
|
||||
return (int) ix;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Predicate each write to memory in LOOP.
|
||||
|
||||
This function transforms control flow constructs containing memory
|
||||
@ -2085,6 +2099,8 @@ static void
|
||||
predicate_mem_writes (loop_p loop)
|
||||
{
|
||||
unsigned int i, orig_loop_num_nodes = loop->num_nodes;
|
||||
auto_vec<int, 1> vect_sizes;
|
||||
auto_vec<tree, 1> vect_masks;
|
||||
|
||||
for (i = 1; i < orig_loop_num_nodes; i++)
|
||||
{
|
||||
@ -2093,6 +2109,7 @@ predicate_mem_writes (loop_p loop)
|
||||
tree cond = bb_predicate (bb);
|
||||
bool swap;
|
||||
gimple stmt;
|
||||
int index;
|
||||
|
||||
if (is_true_predicate (cond))
|
||||
continue;
|
||||
@ -2104,6 +2121,9 @@ predicate_mem_writes (loop_p loop)
|
||||
cond = TREE_OPERAND (cond, 0);
|
||||
}
|
||||
|
||||
vect_sizes.truncate (0);
|
||||
vect_masks.truncate (0);
|
||||
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
if (!gimple_assign_single_p (stmt = gsi_stmt (gsi)))
|
||||
continue;
|
||||
@ -2114,21 +2134,31 @@ predicate_mem_writes (loop_p loop)
|
||||
tree ref, addr, ptr, masktype, mask_op0, mask_op1, mask;
|
||||
gimple new_stmt;
|
||||
int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (lhs)));
|
||||
|
||||
masktype = build_nonstandard_integer_type (bitsize, 1);
|
||||
mask_op0 = build_int_cst (masktype, swap ? 0 : -1);
|
||||
mask_op1 = build_int_cst (masktype, swap ? -1 : 0);
|
||||
ref = TREE_CODE (lhs) == SSA_NAME ? rhs : lhs;
|
||||
mark_addressable (ref);
|
||||
addr = force_gimple_operand_gsi (&gsi, build_fold_addr_expr (ref),
|
||||
true, NULL_TREE, true,
|
||||
GSI_SAME_STMT);
|
||||
cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond),
|
||||
is_gimple_condexpr, NULL_TREE,
|
||||
true, GSI_SAME_STMT);
|
||||
mask = fold_build_cond_expr (masktype, unshare_expr (cond),
|
||||
mask_op0, mask_op1);
|
||||
mask = ifc_temp_var (masktype, mask, &gsi);
|
||||
if (!vect_sizes.is_empty ()
|
||||
&& (index = mask_exists (bitsize, vect_sizes)) != -1)
|
||||
/* Use created mask. */
|
||||
mask = vect_masks[index];
|
||||
else
|
||||
{
|
||||
masktype = build_nonstandard_integer_type (bitsize, 1);
|
||||
mask_op0 = build_int_cst (masktype, swap ? 0 : -1);
|
||||
mask_op1 = build_int_cst (masktype, swap ? -1 : 0);
|
||||
cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond),
|
||||
is_gimple_condexpr,
|
||||
NULL_TREE,
|
||||
true, GSI_SAME_STMT);
|
||||
mask = fold_build_cond_expr (masktype, unshare_expr (cond),
|
||||
mask_op0, mask_op1);
|
||||
mask = ifc_temp_var (masktype, mask, &gsi);
|
||||
/* Save mask and its size for further use. */
|
||||
vect_sizes.safe_push (bitsize);
|
||||
vect_masks.safe_push (mask);
|
||||
}
|
||||
ptr = build_int_cst (reference_alias_ptr_type (ref), 0);
|
||||
/* Copy points-to info if possible. */
|
||||
if (TREE_CODE (addr) == SSA_NAME && !SSA_NAME_PTR_INFO (addr))
|
||||
@ -2494,10 +2524,10 @@ ifcvt_walk_pattern_tree (tree var, vec<gimple> *defuse_list,
|
||||
}
|
||||
|
||||
/* Returns true if STMT can be a root of bool pattern apllied
|
||||
by vectorizer. VAR contains SSA_NAME which starts pattern. */
|
||||
by vectorizer. */
|
||||
|
||||
static bool
|
||||
stmt_is_root_of_bool_pattern (gimple stmt, tree *var)
|
||||
stmt_is_root_of_bool_pattern (gimple stmt)
|
||||
{
|
||||
enum tree_code code;
|
||||
tree lhs, rhs;
|
||||
@ -2511,7 +2541,6 @@ stmt_is_root_of_bool_pattern (gimple stmt, tree *var)
|
||||
return false;
|
||||
if (TREE_CODE (TREE_TYPE (lhs)) == BOOLEAN_TYPE)
|
||||
return false;
|
||||
*var = rhs;
|
||||
return true;
|
||||
}
|
||||
else if (code == COND_EXPR)
|
||||
@ -2519,7 +2548,6 @@ stmt_is_root_of_bool_pattern (gimple stmt, tree *var)
|
||||
rhs = gimple_assign_rhs1 (stmt);
|
||||
if (TREE_CODE (rhs) != SSA_NAME)
|
||||
return false;
|
||||
*var = rhs;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -2538,23 +2566,49 @@ ifcvt_repair_bool_pattern (basic_block bb)
|
||||
gimple stmt;
|
||||
gimple_stmt_iterator gsi;
|
||||
vec<gimple> defuse_list = vNULL;
|
||||
vec<gimple> pattern_roots = vNULL;
|
||||
bool repeat = true;
|
||||
int niter = 0;
|
||||
unsigned int ix;
|
||||
|
||||
/* Collect all root pattern statements. */
|
||||
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
|
||||
{
|
||||
stmt = gsi_stmt (gsi);
|
||||
if (gimple_code (stmt) != GIMPLE_ASSIGN)
|
||||
continue;
|
||||
if (!stmt_is_root_of_bool_pattern (stmt, &rhs))
|
||||
if (!stmt_is_root_of_bool_pattern (stmt))
|
||||
continue;
|
||||
ifcvt_walk_pattern_tree (rhs, &defuse_list, stmt);
|
||||
while (defuse_list.length () > 0)
|
||||
pattern_roots.safe_push (stmt);
|
||||
}
|
||||
|
||||
if (pattern_roots.is_empty ())
|
||||
return;
|
||||
|
||||
/* Split all statements with multiple uses iteratively since splitting
|
||||
may create new multiple uses. */
|
||||
while (repeat)
|
||||
{
|
||||
repeat = false;
|
||||
niter++;
|
||||
FOR_EACH_VEC_ELT (pattern_roots, ix, stmt)
|
||||
{
|
||||
gimple def_stmt, use_stmt;
|
||||
use_stmt = defuse_list.pop ();
|
||||
def_stmt = defuse_list.pop ();
|
||||
ifcvt_split_def_stmt (def_stmt, use_stmt);
|
||||
rhs = gimple_assign_rhs1 (stmt);
|
||||
ifcvt_walk_pattern_tree (rhs, &defuse_list, stmt);
|
||||
while (defuse_list.length () > 0)
|
||||
{
|
||||
repeat = true;
|
||||
gimple def_stmt, use_stmt;
|
||||
use_stmt = defuse_list.pop ();
|
||||
def_stmt = defuse_list.pop ();
|
||||
ifcvt_split_def_stmt (def_stmt, use_stmt);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
fprintf (dump_file, "Repair bool pattern takes %d iterations. \n",
|
||||
niter);
|
||||
}
|
||||
|
||||
/* Delete redundant statements produced by predication which prevents
|
||||
|
Loading…
x
Reference in New Issue
Block a user