Commit f7e531cf by Ira Rosen Committed by Ira Rosen

tree-vectorizer.h (vectorizable_condition): Add argument.


        * tree-vectorizer.h (vectorizable_condition): Add argument.
        * tree-vect-loop.c (vectorizable_reduction): Fail for condition
        in SLP.  Update calls to vectorizable_condition.
        * tree-vect-stmts.c (vect_is_simple_cond): Add basic block info
        to the arguments.  Pass it to vect_is_simple_use_1.
        (vectorizable_condition): Add slp_node to the arguments.
        Support vectorization of basic blocks.  Fail for reduction in
        SLP.  Update calls to vect_is_simple_cond and
        vect_is_simple_use.  Support SLP: call vect_get_slp_defs to get
        vector operands.
        (vect_analyze_stmt): Update calls to vectorizable_condition.
        (vect_transform_stmt): Likewise.
        * tree-vect-slp.c (vect_create_new_slp_node): Handle COND_EXPR.
        (vect_get_and_check_slp_defs): Handle COND_EXPR.  Allow pattern
        def stmts.
        (vect_build_slp_tree): Handle COND_EXPR.
        (vect_analyze_slp_instance): Push pattern statements to root
        node.
        (vect_get_constant_vectors): Fix comments.  Handle COND_EXPR.

From-SVN: r181026
parent 79cad86d
2011-11-06 Ira Rosen <ira.rosen@linaro.org>
* tree-vectorizer.h (vectorizable_condition): Add argument.
* tree-vect-loop.c (vectorizable_reduction): Fail for condition
in SLP. Update calls to vectorizable_condition.
* tree-vect-stmts.c (vect_is_simple_cond): Add basic block info to
the arguments. Pass it to vect_is_simple_use_1.
(vectorizable_condition): Add slp_node to the arguments. Support
vectorization of basic blocks. Fail for reduction in SLP. Update
calls to vect_is_simple_cond and vect_is_simple_use. Support SLP:
call vect_get_slp_defs to get vector operands.
(vect_analyze_stmt): Update calls to vectorizable_condition.
(vect_transform_stmt): Likewise.
* tree-vect-slp.c (vect_create_new_slp_node): Handle COND_EXPR.
(vect_get_and_check_slp_defs): Handle COND_EXPR. Allow pattern
def stmts.
(vect_build_slp_tree): Handle COND_EXPR.
(vect_analyze_slp_instance): Push pattern statements to root node.
(vect_get_constant_vectors): Fix comments. Handle COND_EXPR.
2011-11-05 David S. Miller <davem@davemloft.net> 2011-11-05 David S. Miller <davem@davemloft.net>
* config/sparc/sparc.md (UNSPEC_SHORT_LOAD): New unspec. * config/sparc/sparc.md (UNSPEC_SHORT_LOAD): New unspec.
2011-11-06 Ira Rosen <ira.rosen@linaro.org>
* gcc.dg/vect/bb-slp-cond-1.c: New test.
* gcc.dg/vect/slp-cond-1.c: New test.
* gcc.dg/vect/slp-cond-2.c: New test.
2011-11-05 David S. Miller <davem@davemloft.net> 2011-11-05 David S. Miller <davem@davemloft.net>
* lib/test-supports.exp * lib/test-supports.exp
......
/* { dg-require-effective-target vect_condition } */
#include "tree-vect.h"
#define N 128
__attribute__((noinline, noclone)) void
foo (int *a, int stride)
{
int i;
for (i = 0; i < N/stride; i++, a += stride)
{
a[0] = a[0] ? 1 : 5;
a[1] = a[1] ? 2 : 6;
a[2] = a[2] ? 3 : 7;
a[3] = a[3] ? 4 : 8;
}
}
int a[N];
int main ()
{
int i;
check_vect ();
for (i = 0; i < N; i++)
a[i] = i;
foo (a, 4);
for (i = 1; i < N; i++)
if (a[i] != i%4 + 1)
abort ();
if (a[0] != 5)
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target vect_element_align } } } */
/* { dg-final { cleanup-tree-dump "slp" } } */
/* { dg-require-effective-target vect_condition } */
#include "tree-vect.h"
#define N 32
int a[N], b[N];
int d[N], e[N];
int k[N];
__attribute__((noinline, noclone)) void
f1 (void)
{
int i;
for (i = 0; i < N/4; i++)
{
k[4*i] = a[4*i] < b[4*i] ? 17 : 0;
k[4*i+1] = a[4*i+1] < b[4*i+1] ? 17 : 0;
k[4*i+2] = a[4*i+2] < b[4*i+2] ? 17 : 0;
k[4*i+3] = a[4*i+3] < b[4*i+3] ? 17 : 0;
}
}
__attribute__((noinline, noclone)) void
f2 (void)
{
int i;
for (i = 0; i < N/2; ++i)
{
k[2*i] = a[2*i] < b[2*i] ? 0 : 24;
k[2*i+1] = a[2*i+1] < b[2*i+1] ? 7 : 4;
}
}
__attribute__((noinline, noclone)) void
f3 (void)
{
int i;
for (i = 0; i < N/2; ++i)
{
k[2*i] = a[2*i] < b[2*i] ? 51 : 12;
k[2*i+1] = a[2*i+1] > b[2*i+1] ? 51 : 12;
}
}
__attribute__((noinline, noclone)) void
f4 (void)
{
int i;
for (i = 0; i < N/2; ++i)
{
int d0 = d[2*i], e0 = e[2*i];
int d1 = d[2*i+1], e1 = e[2*i+1];
k[2*i] = a[2*i] >= b[2*i] ? d0 : e0;
k[2*i+1] = a[2*i+1] >= b[2*i+1] ? d1 : e1;
}
}
int
main ()
{
int i;
check_vect ();
for (i = 0; i < N; i++)
{
switch (i % 9)
{
case 0: asm (""); a[i] = - i - 1; b[i] = i + 1; break;
case 1: a[i] = 0; b[i] = 0; break;
case 2: a[i] = i + 1; b[i] = - i - 1; break;
case 3: a[i] = i; b[i] = i + 7; break;
case 4: a[i] = i; b[i] = i; break;
case 5: a[i] = i + 16; b[i] = i + 3; break;
case 6: a[i] = - i - 5; b[i] = - i; break;
case 7: a[i] = - i; b[i] = - i; break;
case 8: a[i] = - i; b[i] = - i - 7; break;
}
d[i] = i;
e[i] = 2 * i;
}
f1 ();
for (i = 0; i < N; i++)
if (k[i] != ((i % 3) == 0 ? 17 : 0))
abort ();
f2 ();
for (i = 0; i < N; i++)
{
switch (i % 9)
{
case 0:
case 6:
if (k[i] != ((i/9 % 2) == 0 ? 0 : 7))
abort ();
break;
case 1:
case 5:
case 7:
if (k[i] != ((i/9 % 2) == 0 ? 4 : 24))
abort ();
break;
case 2:
case 4:
case 8:
if (k[i] != ((i/9 % 2) == 0 ? 24 : 4))
abort ();
break;
case 3:
if (k[i] != ((i/9 % 2) == 0 ? 7 : 0))
abort ();
break;
}
}
f3 ();
f4 ();
for (i = 0; i < N; i++)
if (k[i] != ((i % 3) == 0 ? e[i] : d[i]))
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
/* { dg-require-effective-target vect_cond_mixed } */
#include "tree-vect.h"
#define N 32
int d[N], e[N], f[N];
unsigned char k[N];
float a[N], b[N];
__attribute__((noinline, noclone)) void
f1 (void)
{
int i;
for (i = 0; i < N/4; i++)
{
k[4*i] = a[4*i] < b[4*i] ? 17 : 0;
k[4*i+1] = a[4*i+1] < b[4*i+1] ? 17 : 0;
k[4*i+2] = a[4*i+2] < b[4*i+2] ? 17 : 0;
k[4*i+3] = a[4*i+3] < b[4*i+3] ? 17 : 0;
}
}
__attribute__((noinline, noclone)) void
f2 (void)
{
int i;
for (i = 0; i < N/2; ++i)
{
k[2*i] = a[2*i] < b[2*i] ? 0 : 24;
k[2*i+1] = a[2*i+1] < b[2*i+1] ? 7 : 4;
}
}
__attribute__((noinline, noclone)) void
f3 (void)
{
int i;
for (i = 0; i < N/2; ++i)
{
k[2*i] = a[2*i] < b[2*i] ? 51 : 12;
k[2*i+1] = a[2*i+1] > b[2*i+1] ? 51 : 12;
}
}
__attribute__((noinline, noclone)) void
f4 (void)
{
int i;
for (i = 0; i < N/2; ++i)
{
int d0 = d[2*i], e0 = e[2*i];
int d1 = d[2*i+1], e1 = e[2*i+1];
f[2*i] = a[2*i] >= b[2*i] ? d0 : e0;
f[2*i+1] = a[2*i+1] >= b[2*i+1] ? d1 : e1;
}
}
int
main ()
{
int i;
check_vect ();
for (i = 0; i < N; i++)
{
switch (i % 9)
{
case 0: asm (""); a[i] = - i - 1; b[i] = i + 1; break;
case 1: a[i] = 0; b[i] = 0; break;
case 2: a[i] = i + 1; b[i] = - i - 1; break;
case 3: a[i] = i; b[i] = i + 7; break;
case 4: a[i] = i; b[i] = i; break;
case 5: a[i] = i + 16; b[i] = i + 3; break;
case 6: a[i] = - i - 5; b[i] = - i; break;
case 7: a[i] = - i; b[i] = - i; break;
case 8: a[i] = - i; b[i] = - i - 7; break;
}
d[i] = i;
e[i] = 2 * i;
}
f1 ();
for (i = 0; i < N; i++)
if (k[i] != ((i % 3) == 0 ? 17 : 0))
abort ();
f2 ();
for (i = 0; i < N; i++)
{
switch (i % 9)
{
case 0:
case 6:
if (k[i] != ((i/9 % 2) == 0 ? 0 : 7))
abort ();
break;
case 1:
case 5:
case 7:
if (k[i] != ((i/9 % 2) == 0 ? 4 : 24))
abort ();
break;
case 2:
case 4:
case 8:
if (k[i] != ((i/9 % 2) == 0 ? 24 : 4))
abort ();
break;
case 3:
if (k[i] != ((i/9 % 2) == 0 ? 7 : 0))
abort ();
break;
}
}
f3 ();
f4 ();
for (i = 0; i < N; i++)
if (f[i] != ((i % 3) == 0 ? e[i] : d[i]))
abort ();
return 0;
}
/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 3 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
...@@ -4416,6 +4416,9 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -4416,6 +4416,9 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
gcc_unreachable (); gcc_unreachable ();
} }
if (code == COND_EXPR && slp_node)
return false;
scalar_dest = gimple_assign_lhs (stmt); scalar_dest = gimple_assign_lhs (stmt);
scalar_type = TREE_TYPE (scalar_dest); scalar_type = TREE_TYPE (scalar_dest);
if (!POINTER_TYPE_P (scalar_type) && !INTEGRAL_TYPE_P (scalar_type) if (!POINTER_TYPE_P (scalar_type) && !INTEGRAL_TYPE_P (scalar_type)
...@@ -4502,7 +4505,7 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -4502,7 +4505,7 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
if (code == COND_EXPR) if (code == COND_EXPR)
{ {
if (!vectorizable_condition (stmt, gsi, NULL, ops[reduc_index], 0)) if (!vectorizable_condition (stmt, gsi, NULL, ops[reduc_index], 0, NULL))
{ {
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "unsupported condition in reduction"); fprintf (vect_dump, "unsupported condition in reduction");
...@@ -4774,7 +4777,7 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -4774,7 +4777,7 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
gcc_assert (!slp_node); gcc_assert (!slp_node);
vectorizable_condition (stmt, gsi, vec_stmt, vectorizable_condition (stmt, gsi, vec_stmt,
PHI_RESULT (VEC_index (gimple, phis, 0)), PHI_RESULT (VEC_index (gimple, phis, 0)),
reduc_index); reduc_index, NULL);
/* Multiple types are not supported for condition. */ /* Multiple types are not supported for condition. */
break; break;
} }
......
...@@ -109,7 +109,11 @@ vect_create_new_slp_node (VEC (gimple, heap) *scalar_stmts) ...@@ -109,7 +109,11 @@ vect_create_new_slp_node (VEC (gimple, heap) *scalar_stmts)
if (is_gimple_call (stmt)) if (is_gimple_call (stmt))
nops = gimple_call_num_args (stmt); nops = gimple_call_num_args (stmt);
else if (is_gimple_assign (stmt)) else if (is_gimple_assign (stmt))
nops = gimple_num_ops (stmt) - 1; {
nops = gimple_num_ops (stmt) - 1;
if (gimple_assign_rhs_code (stmt) == COND_EXPR)
nops++;
}
else else
return NULL; return NULL;
...@@ -191,20 +195,41 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, ...@@ -191,20 +195,41 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
bool different_types = false; bool different_types = false;
bool pattern = false; bool pattern = false;
slp_oprnd_info oprnd_info, oprnd0_info, oprnd1_info; slp_oprnd_info oprnd_info, oprnd0_info, oprnd1_info;
int op_idx = 1;
tree compare_rhs = NULL_TREE;
if (loop_vinfo) if (loop_vinfo)
loop = LOOP_VINFO_LOOP (loop_vinfo); loop = LOOP_VINFO_LOOP (loop_vinfo);
if (is_gimple_call (stmt)) if (is_gimple_call (stmt))
number_of_oprnds = gimple_call_num_args (stmt); number_of_oprnds = gimple_call_num_args (stmt);
else if (is_gimple_assign (stmt))
{
number_of_oprnds = gimple_num_ops (stmt) - 1;
if (gimple_assign_rhs_code (stmt) == COND_EXPR)
number_of_oprnds++;
}
else else
number_of_oprnds = gimple_num_ops (stmt) - 1; return false;
for (i = 0; i < number_of_oprnds; i++) for (i = 0; i < number_of_oprnds; i++)
{ {
oprnd = gimple_op (stmt, i + 1); if (compare_rhs)
{
oprnd = compare_rhs;
compare_rhs = NULL_TREE;
}
else
oprnd = gimple_op (stmt, op_idx++);
oprnd_info = VEC_index (slp_oprnd_info, *oprnds_info, i); oprnd_info = VEC_index (slp_oprnd_info, *oprnds_info, i);
if (COMPARISON_CLASS_P (oprnd))
{
compare_rhs = TREE_OPERAND (oprnd, 1);
oprnd = TREE_OPERAND (oprnd, 0);
}
if (!vect_is_simple_use (oprnd, loop_vinfo, bb_vinfo, &def_stmt, &def, if (!vect_is_simple_use (oprnd, loop_vinfo, bb_vinfo, &def_stmt, &def,
&dt) &dt)
|| (!def_stmt && dt != vect_constant_def)) || (!def_stmt && dt != vect_constant_def))
...@@ -244,8 +269,7 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, ...@@ -244,8 +269,7 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
def_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)); def_stmt = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt));
dt = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt)); dt = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def_stmt));
if (dt == vect_unknown_def_type if (dt == vect_unknown_def_type)
|| STMT_VINFO_PATTERN_DEF_STMT (vinfo_for_stmt (def_stmt)))
{ {
if (vect_print_dump_info (REPORT_DETAILS)) if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "Unsupported pattern."); fprintf (vect_dump, "Unsupported pattern.");
...@@ -424,6 +448,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, ...@@ -424,6 +448,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
VEC (gimple, heap) *stmts = SLP_TREE_SCALAR_STMTS (*node); VEC (gimple, heap) *stmts = SLP_TREE_SCALAR_STMTS (*node);
gimple stmt = VEC_index (gimple, stmts, 0); gimple stmt = VEC_index (gimple, stmts, 0);
enum tree_code first_stmt_code = ERROR_MARK, rhs_code = ERROR_MARK; enum tree_code first_stmt_code = ERROR_MARK, rhs_code = ERROR_MARK;
enum tree_code first_cond_code = ERROR_MARK;
tree lhs; tree lhs;
bool stop_recursion = false, need_same_oprnds = false; bool stop_recursion = false, need_same_oprnds = false;
tree vectype, scalar_type, first_op1 = NULL_TREE; tree vectype, scalar_type, first_op1 = NULL_TREE;
...@@ -440,11 +465,18 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, ...@@ -440,11 +465,18 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
VEC (slp_oprnd_info, heap) *oprnds_info; VEC (slp_oprnd_info, heap) *oprnds_info;
unsigned int nops; unsigned int nops;
slp_oprnd_info oprnd_info; slp_oprnd_info oprnd_info;
tree cond;
if (is_gimple_call (stmt)) if (is_gimple_call (stmt))
nops = gimple_call_num_args (stmt); nops = gimple_call_num_args (stmt);
else if (is_gimple_assign (stmt))
{
nops = gimple_num_ops (stmt) - 1;
if (gimple_assign_rhs_code (stmt) == COND_EXPR)
nops++;
}
else else
nops = gimple_num_ops (stmt) - 1; return false;
oprnds_info = vect_create_oprnd_info (nops, group_size); oprnds_info = vect_create_oprnd_info (nops, group_size);
...@@ -485,6 +517,22 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, ...@@ -485,6 +517,22 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
return false; return false;
} }
if (is_gimple_assign (stmt)
&& gimple_assign_rhs_code (stmt) == COND_EXPR
&& (cond = gimple_assign_rhs1 (stmt))
&& !COMPARISON_CLASS_P (cond))
{
if (vect_print_dump_info (REPORT_SLP))
{
fprintf (vect_dump,
"Build SLP failed: condition is not comparison ");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
vect_free_oprnd_info (&oprnds_info, true);
return false;
}
scalar_type = vect_get_smallest_scalar_type (stmt, &dummy, &dummy); scalar_type = vect_get_smallest_scalar_type (stmt, &dummy, &dummy);
vectype = get_vectype_for_scalar_type (scalar_type); vectype = get_vectype_for_scalar_type (scalar_type);
if (!vectype) if (!vectype)
...@@ -737,7 +785,8 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, ...@@ -737,7 +785,8 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
/* Not memory operation. */ /* Not memory operation. */
if (TREE_CODE_CLASS (rhs_code) != tcc_binary if (TREE_CODE_CLASS (rhs_code) != tcc_binary
&& TREE_CODE_CLASS (rhs_code) != tcc_unary) && TREE_CODE_CLASS (rhs_code) != tcc_unary
&& rhs_code != COND_EXPR)
{ {
if (vect_print_dump_info (REPORT_SLP)) if (vect_print_dump_info (REPORT_SLP))
{ {
...@@ -750,6 +799,26 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, ...@@ -750,6 +799,26 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
return false; return false;
} }
if (rhs_code == COND_EXPR)
{
tree cond_expr = gimple_assign_rhs1 (stmt);
if (i == 0)
first_cond_code = TREE_CODE (cond_expr);
else if (first_cond_code != TREE_CODE (cond_expr))
{
if (vect_print_dump_info (REPORT_SLP))
{
fprintf (vect_dump, "Build SLP failed: different"
" operation");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
vect_free_oprnd_info (&oprnds_info, true);
return false;
}
}
/* Find the def-stmts. */ /* Find the def-stmts. */
if (!vect_get_and_check_slp_defs (loop_vinfo, bb_vinfo, *node, stmt, if (!vect_get_and_check_slp_defs (loop_vinfo, bb_vinfo, *node, stmt,
ncopies_for_cost, (i == 0), ncopies_for_cost, (i == 0),
...@@ -1402,7 +1471,12 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, ...@@ -1402,7 +1471,12 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
/* Collect the stores and store them in SLP_TREE_SCALAR_STMTS. */ /* Collect the stores and store them in SLP_TREE_SCALAR_STMTS. */
while (next) while (next)
{ {
VEC_safe_push (gimple, heap, scalar_stmts, next); if (STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (next))
&& STMT_VINFO_RELATED_STMT (vinfo_for_stmt (next)))
VEC_safe_push (gimple, heap, scalar_stmts,
STMT_VINFO_RELATED_STMT (vinfo_for_stmt (next)));
else
VEC_safe_push (gimple, heap, scalar_stmts, next);
next = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next)); next = GROUP_NEXT_ELEMENT (vinfo_for_stmt (next));
} }
} }
...@@ -1411,7 +1485,7 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo, ...@@ -1411,7 +1485,7 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
/* Collect reduction statements. */ /* Collect reduction statements. */
VEC (gimple, heap) *reductions = LOOP_VINFO_REDUCTIONS (loop_vinfo); VEC (gimple, heap) *reductions = LOOP_VINFO_REDUCTIONS (loop_vinfo);
for (i = 0; VEC_iterate (gimple, reductions, i, next); i++) for (i = 0; VEC_iterate (gimple, reductions, i, next); i++)
VEC_safe_push (gimple, heap, scalar_stmts, next); VEC_safe_push (gimple, heap, scalar_stmts, next);
} }
node = vect_create_new_slp_node (scalar_stmts); node = vect_create_new_slp_node (scalar_stmts);
...@@ -2150,15 +2224,15 @@ vect_get_constant_vectors (tree op, slp_tree slp_node, ...@@ -2150,15 +2224,15 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
For example, we have two scalar operands, s1 and s2 (e.g., group of For example, we have two scalar operands, s1 and s2 (e.g., group of
strided accesses of size two), while NUNITS is four (i.e., four scalars strided accesses of size two), while NUNITS is four (i.e., four scalars
of this type can be packed in a vector). The output vector will contain of this type can be packed in a vector). The output vector will contain
two copies of each scalar operand: {s1, s2, s1, s2}. (NUMBER_OF_COPIES two copies of each scalar operand: {s1, s2, s1, s2}. (NUMBER_OF_COPIES
will be 2). will be 2).
If GROUP_SIZE > NUNITS, the scalars will be split into several vectors If GROUP_SIZE > NUNITS, the scalars will be split into several vectors
containing the operands. containing the operands.
For example, NUNITS is four as before, and the group size is 8 For example, NUNITS is four as before, and the group size is 8
(s1, s2, ..., s8). We will create two vectors {s1, s2, s3, s4} and (s1, s2, ..., s8). We will create two vectors {s1, s2, s3, s4} and
{s5, s6, s7, s8}. */ {s5, s6, s7, s8}. */
number_of_copies = least_common_multiple (nunits, group_size) / group_size; number_of_copies = least_common_multiple (nunits, group_size) / group_size;
...@@ -2170,8 +2244,23 @@ vect_get_constant_vectors (tree op, slp_tree slp_node, ...@@ -2170,8 +2244,23 @@ vect_get_constant_vectors (tree op, slp_tree slp_node,
{ {
if (is_store) if (is_store)
op = gimple_assign_rhs1 (stmt); op = gimple_assign_rhs1 (stmt);
else else if (gimple_assign_rhs_code (stmt) != COND_EXPR)
op = gimple_op (stmt, op_num + 1); op = gimple_op (stmt, op_num + 1);
else
{
if (op_num == 0 || op_num == 1)
{
tree cond = gimple_assign_rhs1 (stmt);
op = TREE_OPERAND (cond, op_num);
}
else
{
if (op_num == 2)
op = gimple_assign_rhs2 (stmt);
else
op = gimple_assign_rhs3 (stmt);
}
}
if (reduc_index != -1) if (reduc_index != -1)
{ {
......
...@@ -4606,7 +4606,8 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, ...@@ -4606,7 +4606,8 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
condition operands are supportable using vec_is_simple_use. */ condition operands are supportable using vec_is_simple_use. */
static bool static bool
vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype) vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
tree *comp_vectype)
{ {
tree lhs, rhs; tree lhs, rhs;
tree def; tree def;
...@@ -4622,7 +4623,7 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype) ...@@ -4622,7 +4623,7 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype)
if (TREE_CODE (lhs) == SSA_NAME) if (TREE_CODE (lhs) == SSA_NAME)
{ {
gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs); gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
if (!vect_is_simple_use_1 (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def, if (!vect_is_simple_use_1 (lhs, loop_vinfo, bb_vinfo, &lhs_def_stmt, &def,
&dt, &vectype1)) &dt, &vectype1))
return false; return false;
} }
...@@ -4633,11 +4634,11 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype) ...@@ -4633,11 +4634,11 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype)
if (TREE_CODE (rhs) == SSA_NAME) if (TREE_CODE (rhs) == SSA_NAME)
{ {
gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs); gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
if (!vect_is_simple_use_1 (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def, if (!vect_is_simple_use_1 (rhs, loop_vinfo, bb_vinfo, &rhs_def_stmt, &def,
&dt, &vectype2)) &dt, &vectype2))
return false; return false;
} }
else if (TREE_CODE (rhs) != INTEGER_CST && TREE_CODE (rhs) != REAL_CST else if (TREE_CODE (rhs) != INTEGER_CST && TREE_CODE (rhs) != REAL_CST
&& TREE_CODE (rhs) != FIXED_CST) && TREE_CODE (rhs) != FIXED_CST)
return false; return false;
...@@ -4660,7 +4661,8 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype) ...@@ -4660,7 +4661,8 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo, tree *comp_vectype)
bool bool
vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi, vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
gimple *vec_stmt, tree reduc_def, int reduc_index) gimple *vec_stmt, tree reduc_def, int reduc_index,
slp_tree slp_node)
{ {
tree scalar_dest = NULL_TREE; tree scalar_dest = NULL_TREE;
tree vec_dest = NULL_TREE; tree vec_dest = NULL_TREE;
...@@ -4676,23 +4678,27 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -4676,23 +4678,27 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
tree def; tree def;
enum vect_def_type dt, dts[4]; enum vect_def_type dt, dts[4];
int nunits = TYPE_VECTOR_SUBPARTS (vectype); int nunits = TYPE_VECTOR_SUBPARTS (vectype);
int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits; int ncopies;
enum tree_code code; enum tree_code code;
stmt_vec_info prev_stmt_info = NULL; stmt_vec_info prev_stmt_info = NULL;
int j; int i, j;
bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
/* FORNOW: unsupported in basic block SLP. */ VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
gcc_assert (loop_vinfo); VEC (tree, heap) *vec_oprnds2 = NULL, *vec_oprnds3 = NULL;
/* FORNOW: SLP not supported. */ if (slp_node || PURE_SLP_STMT (stmt_info))
if (STMT_SLP_TYPE (stmt_info)) ncopies = 1;
return false; else
ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
gcc_assert (ncopies >= 1); gcc_assert (ncopies >= 1);
if (reduc_index && ncopies > 1) if (reduc_index && ncopies > 1)
return false; /* FORNOW */ return false; /* FORNOW */
if (!STMT_VINFO_RELEVANT_P (stmt_info)) if (reduc_index && STMT_SLP_TYPE (stmt_info))
return false;
if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
return false; return false;
if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def
...@@ -4721,14 +4727,14 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -4721,14 +4727,14 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
then_clause = gimple_assign_rhs2 (stmt); then_clause = gimple_assign_rhs2 (stmt);
else_clause = gimple_assign_rhs3 (stmt); else_clause = gimple_assign_rhs3 (stmt);
if (!vect_is_simple_cond (cond_expr, loop_vinfo, &comp_vectype) if (!vect_is_simple_cond (cond_expr, loop_vinfo, bb_vinfo, &comp_vectype)
|| !comp_vectype) || !comp_vectype)
return false; return false;
if (TREE_CODE (then_clause) == SSA_NAME) if (TREE_CODE (then_clause) == SSA_NAME)
{ {
gimple then_def_stmt = SSA_NAME_DEF_STMT (then_clause); gimple then_def_stmt = SSA_NAME_DEF_STMT (then_clause);
if (!vect_is_simple_use (then_clause, loop_vinfo, NULL, if (!vect_is_simple_use (then_clause, loop_vinfo, bb_vinfo,
&then_def_stmt, &def, &dt)) &then_def_stmt, &def, &dt))
return false; return false;
} }
...@@ -4740,7 +4746,7 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -4740,7 +4746,7 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
if (TREE_CODE (else_clause) == SSA_NAME) if (TREE_CODE (else_clause) == SSA_NAME)
{ {
gimple else_def_stmt = SSA_NAME_DEF_STMT (else_clause); gimple else_def_stmt = SSA_NAME_DEF_STMT (else_clause);
if (!vect_is_simple_use (else_clause, loop_vinfo, NULL, if (!vect_is_simple_use (else_clause, loop_vinfo, bb_vinfo,
&else_def_stmt, &def, &dt)) &else_def_stmt, &def, &dt))
return false; return false;
} }
...@@ -4755,7 +4761,15 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -4755,7 +4761,15 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
return expand_vec_cond_expr_p (vectype, comp_vectype); return expand_vec_cond_expr_p (vectype, comp_vectype);
} }
/* Transform */ /* Transform. */
if (!slp_node)
{
vec_oprnds0 = VEC_alloc (tree, heap, 1);
vec_oprnds1 = VEC_alloc (tree, heap, 1);
vec_oprnds2 = VEC_alloc (tree, heap, 1);
vec_oprnds3 = VEC_alloc (tree, heap, 1);
}
/* Handle def. */ /* Handle def. */
scalar_dest = gimple_assign_lhs (stmt); scalar_dest = gimple_assign_lhs (stmt);
...@@ -4764,67 +4778,118 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -4764,67 +4778,118 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
/* Handle cond expr. */ /* Handle cond expr. */
for (j = 0; j < ncopies; j++) for (j = 0; j < ncopies; j++)
{ {
gimple new_stmt; gimple new_stmt = NULL;
if (j == 0) if (j == 0)
{ {
gimple gtemp; if (slp_node)
vec_cond_lhs = {
VEC (tree, heap) *ops = VEC_alloc (tree, heap, 4);
VEC (slp_void_p, heap) *vec_defs;
vec_defs = VEC_alloc (slp_void_p, heap, 4);
VEC_safe_push (tree, heap, ops, TREE_OPERAND (cond_expr, 0));
VEC_safe_push (tree, heap, ops, TREE_OPERAND (cond_expr, 1));
VEC_safe_push (tree, heap, ops, then_clause);
VEC_safe_push (tree, heap, ops, else_clause);
vect_get_slp_defs (ops, slp_node, &vec_defs, -1);
vec_oprnds3 = (VEC (tree, heap) *) VEC_pop (slp_void_p, vec_defs);
vec_oprnds2 = (VEC (tree, heap) *) VEC_pop (slp_void_p, vec_defs);
vec_oprnds1 = (VEC (tree, heap) *) VEC_pop (slp_void_p, vec_defs);
vec_oprnds0 = (VEC (tree, heap) *) VEC_pop (slp_void_p, vec_defs);
VEC_free (tree, heap, ops);
VEC_free (slp_void_p, heap, vec_defs);
}
else
{
gimple gtemp;
vec_cond_lhs =
vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0),
stmt, NULL); stmt, NULL);
vect_is_simple_use (TREE_OPERAND (cond_expr, 0), loop_vinfo, vect_is_simple_use (TREE_OPERAND (cond_expr, 0), loop_vinfo,
NULL, &gtemp, &def, &dts[0]); NULL, &gtemp, &def, &dts[0]);
vec_cond_rhs =
vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), vec_cond_rhs =
stmt, NULL); vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1),
vect_is_simple_use (TREE_OPERAND (cond_expr, 1), loop_vinfo, stmt, NULL);
NULL, &gtemp, &def, &dts[1]); vect_is_simple_use (TREE_OPERAND (cond_expr, 1), loop_vinfo,
if (reduc_index == 1) NULL, &gtemp, &def, &dts[1]);
vec_then_clause = reduc_def; if (reduc_index == 1)
else vec_then_clause = reduc_def;
{ else
vec_then_clause = vect_get_vec_def_for_operand (then_clause, {
stmt, NULL); vec_then_clause = vect_get_vec_def_for_operand (then_clause,
vect_is_simple_use (then_clause, loop_vinfo, stmt, NULL);
NULL, &gtemp, &def, &dts[2]); vect_is_simple_use (then_clause, loop_vinfo,
} NULL, &gtemp, &def, &dts[2]);
if (reduc_index == 2) }
vec_else_clause = reduc_def; if (reduc_index == 2)
else vec_else_clause = reduc_def;
{ else
vec_else_clause = vect_get_vec_def_for_operand (else_clause, {
vec_else_clause = vect_get_vec_def_for_operand (else_clause,
stmt, NULL); stmt, NULL);
vect_is_simple_use (else_clause, loop_vinfo, vect_is_simple_use (else_clause, loop_vinfo,
NULL, &gtemp, &def, &dts[3]); NULL, &gtemp, &def, &dts[3]);
}
} }
} }
else else
{ {
vec_cond_lhs = vect_get_vec_def_for_stmt_copy (dts[0], vec_cond_lhs); vec_cond_lhs = vect_get_vec_def_for_stmt_copy (dts[0],
vec_cond_rhs = vect_get_vec_def_for_stmt_copy (dts[1], vec_cond_rhs); VEC_pop (tree, vec_oprnds0));
vec_cond_rhs = vect_get_vec_def_for_stmt_copy (dts[1],
VEC_pop (tree, vec_oprnds1));
vec_then_clause = vect_get_vec_def_for_stmt_copy (dts[2], vec_then_clause = vect_get_vec_def_for_stmt_copy (dts[2],
vec_then_clause); VEC_pop (tree, vec_oprnds2));
vec_else_clause = vect_get_vec_def_for_stmt_copy (dts[3], vec_else_clause = vect_get_vec_def_for_stmt_copy (dts[3],
vec_else_clause); VEC_pop (tree, vec_oprnds3));
}
if (!slp_node)
{
VEC_quick_push (tree, vec_oprnds0, vec_cond_lhs);
VEC_quick_push (tree, vec_oprnds1, vec_cond_rhs);
VEC_quick_push (tree, vec_oprnds2, vec_then_clause);
VEC_quick_push (tree, vec_oprnds3, vec_else_clause);
} }
/* Arguments are ready. Create the new vector stmt. */ /* Arguments are ready. Create the new vector stmt. */
vec_compare = build2 (TREE_CODE (cond_expr), vectype, FOR_EACH_VEC_ELT (tree, vec_oprnds0, i, vec_cond_lhs)
vec_cond_lhs, vec_cond_rhs); {
vec_cond_expr = build3 (VEC_COND_EXPR, vectype, vec_cond_rhs = VEC_index (tree, vec_oprnds1, i);
vec_compare, vec_then_clause, vec_else_clause); vec_then_clause = VEC_index (tree, vec_oprnds2, i);
vec_else_clause = VEC_index (tree, vec_oprnds3, i);
new_stmt = gimple_build_assign (vec_dest, vec_cond_expr); vec_compare = build2 (TREE_CODE (cond_expr), vectype,
new_temp = make_ssa_name (vec_dest, new_stmt); vec_cond_lhs, vec_cond_rhs);
gimple_assign_set_lhs (new_stmt, new_temp); vec_cond_expr = build3 (VEC_COND_EXPR, vectype,
vect_finish_stmt_generation (stmt, new_stmt, gsi); vec_compare, vec_then_clause, vec_else_clause);
if (j == 0)
STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
else
STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
prev_stmt_info = vinfo_for_stmt (new_stmt); new_stmt = gimple_build_assign (vec_dest, vec_cond_expr);
new_temp = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, new_temp);
vect_finish_stmt_generation (stmt, new_stmt, gsi);
if (slp_node)
VEC_quick_push (gimple, SLP_TREE_VEC_STMTS (slp_node), new_stmt);
}
if (slp_node)
continue;
if (j == 0)
STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
else
STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
prev_stmt_info = vinfo_for_stmt (new_stmt);
} }
VEC_free (tree, heap, vec_oprnds0);
VEC_free (tree, heap, vec_oprnds1);
VEC_free (tree, heap, vec_oprnds2);
VEC_free (tree, heap, vec_oprnds3);
return true; return true;
} }
...@@ -4996,7 +5061,7 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node) ...@@ -4996,7 +5061,7 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
|| vectorizable_call (stmt, NULL, NULL) || vectorizable_call (stmt, NULL, NULL)
|| vectorizable_store (stmt, NULL, NULL, NULL) || vectorizable_store (stmt, NULL, NULL, NULL)
|| vectorizable_reduction (stmt, NULL, NULL, NULL) || vectorizable_reduction (stmt, NULL, NULL, NULL)
|| vectorizable_condition (stmt, NULL, NULL, NULL, 0)); || vectorizable_condition (stmt, NULL, NULL, NULL, 0, NULL));
else else
{ {
if (bb_vinfo) if (bb_vinfo)
...@@ -5005,7 +5070,8 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node) ...@@ -5005,7 +5070,8 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
|| vectorizable_operation (stmt, NULL, NULL, node) || vectorizable_operation (stmt, NULL, NULL, node)
|| vectorizable_assignment (stmt, NULL, NULL, node) || vectorizable_assignment (stmt, NULL, NULL, node)
|| vectorizable_load (stmt, NULL, NULL, node, NULL) || vectorizable_load (stmt, NULL, NULL, node, NULL)
|| vectorizable_store (stmt, NULL, NULL, node)); || vectorizable_store (stmt, NULL, NULL, node)
|| vectorizable_condition (stmt, NULL, NULL, NULL, 0, node));
} }
if (!ok) if (!ok)
...@@ -5113,8 +5179,7 @@ vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi, ...@@ -5113,8 +5179,7 @@ vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi,
break; break;
case condition_vec_info_type: case condition_vec_info_type:
gcc_assert (!slp_node); done = vectorizable_condition (stmt, gsi, &vec_stmt, NULL, 0, slp_node);
done = vectorizable_condition (stmt, gsi, &vec_stmt, NULL, 0);
gcc_assert (done); gcc_assert (done);
break; break;
......
...@@ -837,7 +837,7 @@ extern bool vect_transform_stmt (gimple, gimple_stmt_iterator *, ...@@ -837,7 +837,7 @@ extern bool vect_transform_stmt (gimple, gimple_stmt_iterator *,
extern void vect_remove_stores (gimple); extern void vect_remove_stores (gimple);
extern bool vect_analyze_stmt (gimple, bool *, slp_tree); extern bool vect_analyze_stmt (gimple, bool *, slp_tree);
extern bool vectorizable_condition (gimple, gimple_stmt_iterator *, gimple *, extern bool vectorizable_condition (gimple, gimple_stmt_iterator *, gimple *,
tree, int); tree, int, slp_tree);
extern void vect_get_load_cost (struct data_reference *, int, bool, extern void vect_get_load_cost (struct data_reference *, int, bool,
unsigned int *, unsigned int *); unsigned int *, unsigned int *);
extern void vect_get_store_cost (struct data_reference *, int, unsigned int *); extern void vect_get_store_cost (struct data_reference *, int, unsigned int *);
......
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