diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2018-08-03 12:56:55 +0000 |
---|---|---|
committer | Richard Sandiford <rsandifo@gcc.gnu.org> | 2018-08-03 12:56:55 +0000 |
commit | 0246112a9d59b22cc06165b6586b8dc0d76b72a1 (patch) | |
tree | c5cea056f707c9b77bae206e6dad99911f65d947 /gcc/tree-vect-slp.c | |
parent | d7487e2ae8666f071cb841a845e1e8770b4f9f67 (diff) | |
download | gcc-0246112a9d59b22cc06165b6586b8dc0d76b72a1.zip gcc-0246112a9d59b22cc06165b6586b8dc0d76b72a1.tar.gz gcc-0246112a9d59b22cc06165b6586b8dc0d76b72a1.tar.bz2 |
Handle SLP of call pattern statements
We couldn't vectorise:
for (int j = 0; j < n; ++j)
{
for (int i = 0; i < 16; ++i)
a[i] = (b[i] + c[i]) >> 1;
a += step;
b += step;
c += step;
}
at -O3 because cunrolli unrolled the inner loop and SLP couldn't handle
AVG_FLOOR patterns (see also PR86504). The problem was some overly
strict checking of pattern statements compared to normal statements
in vect_get_and_check_slp_defs:
switch (gimple_code (def_stmt))
{
case GIMPLE_PHI:
case GIMPLE_ASSIGN:
break;
default:
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"unsupported defining stmt:\n");
return -1;
}
The easy fix would have been to add GIMPLE_CALL to the switch,
but I don't think the switch is doing anything useful. We only create
pattern statements that the rest of the vectoriser can handle, and the
other checks in this function and elsewhere check whether SLP is possible.
I'm also not sure why:
if (!first && !oprnd_info->first_pattern
/* Allow different pattern state for the defs of the
first stmt in reduction chains. */
&& (oprnd_info->first_dt != vect_reduction_def
is necessary. All that should matter is that the statements in the
node are "similar enough". It turned out to be quite hard to find a
convincing example that used a mixture of pattern and non-pattern
statements, so bb-slp-pow-1.c is the best I could come up with.
But it does show that the combination of "xi * xi" statements and
"pow (xj, 2) -> xj * xj" patterns are handled correctly.
The patch therefore just removes the whole if block.
The loop also needed commutative swapping to be extended to at least
AVG_FLOOR.
This gives +3.9% on 525.x264_r at -O3.
2018-08-03 Richard Sandiford <richard.sandiford@arm.com>
gcc/
* internal-fn.h (first_commutative_argument): Declare.
* internal-fn.c (first_commutative_argument): New function.
* tree-vect-slp.c (vect_get_and_check_slp_defs): Remove extra
restrictions for pattern statements. Use first_commutative_argument
to look for commutative operands in calls to internal functions.
gcc/testsuite/
* gcc.dg/vect/bb-slp-over-widen-1.c: Expect AVG_FLOOR to be used
on vect_avg_qi targets.
* gcc.dg/vect/bb-slp-over-widen-2.c: Likewise.
* gcc.dg/vect/bb-slp-pow-1.c: New test.
* gcc.dg/vect/vect-avg-15.c: Likewise.
From-SVN: r263290
Diffstat (limited to 'gcc/tree-vect-slp.c')
-rw-r--r-- | gcc/tree-vect-slp.c | 81 |
1 files changed, 16 insertions, 65 deletions
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index d0f6da4..367945b 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -309,7 +309,7 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char *swap, bool pattern = false; slp_oprnd_info oprnd_info; int first_op_idx = 1; - bool commutative = false; + unsigned int commutative_op = -1U; bool first_op_cond = false; bool first = stmt_num == 0; bool second = stmt_num == 1; @@ -318,6 +318,11 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char *swap, { number_of_oprnds = gimple_call_num_args (stmt); first_op_idx = 3; + if (gimple_call_internal_p (stmt)) + { + internal_fn ifn = gimple_call_internal_fn (stmt); + commutative_op = first_commutative_argument (ifn); + } } else if (gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt)) { @@ -332,7 +337,7 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char *swap, number_of_oprnds++; } else - commutative = commutative_tree_code (code); + commutative_op = commutative_tree_code (code) ? 0U : -1U; } else return -1; @@ -373,62 +378,6 @@ again: return -1; } - /* Check if DEF_STMT_INFO is a part of a pattern in LOOP and get - the def stmt from the pattern. Check that all the stmts of the - node are in the pattern. */ - if (def_stmt_info && is_pattern_stmt_p (def_stmt_info)) - { - pattern = true; - if (!first && !oprnd_info->first_pattern - /* Allow different pattern state for the defs of the - first stmt in reduction chains. */ - && (oprnd_info->first_dt != vect_reduction_def - || (!second && !oprnd_info->second_pattern))) - { - if (i == 0 - && !swapped - && commutative) - { - swapped = true; - goto again; - } - - if (dump_enabled_p ()) - { - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "Build SLP failed: some of the stmts" - " are in a pattern, and others are not "); - dump_generic_expr (MSG_MISSED_OPTIMIZATION, TDF_SLIM, oprnd); - dump_printf (MSG_MISSED_OPTIMIZATION, "\n"); - } - - return 1; - } - - dt = STMT_VINFO_DEF_TYPE (def_stmt_info); - - if (dt == vect_unknown_def_type) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "Unsupported pattern.\n"); - return -1; - } - - switch (gimple_code (def_stmt_info->stmt)) - { - case GIMPLE_PHI: - case GIMPLE_ASSIGN: - break; - - default: - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "unsupported defining stmt:\n"); - return -1; - } - } - if (second) oprnd_info->second_pattern = pattern; @@ -456,9 +405,7 @@ again: || !types_compatible_p (oprnd_info->first_op_type, type)) { /* Try swapping operands if we got a mismatch. */ - if (i == 0 - && !swapped - && commutative) + if (i == commutative_op && !swapped) { swapped = true; goto again; @@ -534,9 +481,9 @@ again: return -1; } - gassign *stmt = as_a <gassign *> (stmt_info->stmt); if (first_op_cond) { + gassign *stmt = as_a <gassign *> (stmt_info->stmt); tree cond = gimple_assign_rhs1 (stmt); enum tree_code code = TREE_CODE (cond); @@ -559,13 +506,17 @@ again: } } else - swap_ssa_operands (stmt, gimple_assign_rhs1_ptr (stmt), - gimple_assign_rhs2_ptr (stmt)); + { + unsigned int op = commutative_op + first_op_idx; + swap_ssa_operands (stmt_info->stmt, + gimple_op_ptr (stmt_info->stmt, op), + gimple_op_ptr (stmt_info->stmt, op + 1)); + } if (dump_enabled_p ()) { dump_printf_loc (MSG_NOTE, vect_location, "swapped operands to match def types in "); - dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt, 0); + dump_gimple_stmt (MSG_NOTE, TDF_SLIM, stmt_info->stmt, 0); } } |