Re: [PATCH][RFC] Handle commutative operations in SLP tree build

2013-04-17 Thread Richard Biener
On Wed, 10 Apr 2013, Richard Biener wrote:

> 
> This handles commutative operations during SLP tree build in the
> way that if one configuration does not match, the build will
> try again with commutated operands for.  This allows to remove
> the special-casing of commutated loads in a complex addition
> that was in the end handled as "permutation".  It of course
> also applies more generally.  Permutation is currently limited
> to 3 unsuccessful permutes to avoid running into the inherently
> exponential complexity of tree matching.
> 
> The gcc.dg/vect/vect-complex-?.c testcases provide some testing
> coverage (previously handled by the special-casing).  I have
> seen failed SLP in the wild previously but it's usually on
> larger testcases and dependent on operand order of commutative
> operands.
> 
> I've discussed ideas to restrict the cases where we try a permutation
> with Matz, but I'll rather defer that to an eventual followup.
> (compute per SSA name a value dependent on the shape of its
> use-def tree and use that as a quick check whether sub-trees
> can possibly match)
> 
> Bootstrap and regtest running on x86_64-unknown-linux-gnu.
> 
> Any comments?

Committed to trunk.

Richard.

> 2013-04-10  Richard Biener  
> 
>   * tree-vect-slp.c (vect_build_slp_tree_1): Split out from ...
>   (vect_build_slp_tree): ... here.
>   (vect_build_slp_tree_1): Compute which stmts of the SLP group
>   match.  Remove special-casing of mismatched complex loads.
>   (vect_build_slp_tree): Based on the result from vect_build_slp_tree_1
>   re-try the match with swapped commutative operands.
>   (vect_supported_load_permutation_p): Remove special-casing of
>   mismatched complex loads.
>   (vect_analyze_slp_instance): Adjust.


[PATCH][RFC] Handle commutative operations in SLP tree build

2013-04-10 Thread Richard Biener

This handles commutative operations during SLP tree build in the
way that if one configuration does not match, the build will
try again with commutated operands for.  This allows to remove
the special-casing of commutated loads in a complex addition
that was in the end handled as "permutation".  It of course
also applies more generally.  Permutation is currently limited
to 3 unsuccessful permutes to avoid running into the inherently
exponential complexity of tree matching.

The gcc.dg/vect/vect-complex-?.c testcases provide some testing
coverage (previously handled by the special-casing).  I have
seen failed SLP in the wild previously but it's usually on
larger testcases and dependent on operand order of commutative
operands.

I've discussed ideas to restrict the cases where we try a permutation
with Matz, but I'll rather defer that to an eventual followup.
(compute per SSA name a value dependent on the shape of its
use-def tree and use that as a quick check whether sub-trees
can possibly match)

Bootstrap and regtest running on x86_64-unknown-linux-gnu.

Any comments?

Thanks,
Richard.

2013-04-10  Richard Biener  

* tree-vect-slp.c (vect_build_slp_tree_1): Split out from ...
(vect_build_slp_tree): ... here.
(vect_build_slp_tree_1): Compute which stmts of the SLP group
match.  Remove special-casing of mismatched complex loads.
(vect_build_slp_tree): Based on the result from vect_build_slp_tree_1
re-try the match with swapped commutative operands.
(vect_supported_load_permutation_p): Remove special-casing of
mismatched complex loads.
(vect_analyze_slp_instance): Adjust.

Index: trunk/gcc/tree-vect-slp.c
===
*** trunk.orig/gcc/tree-vect-slp.c  2013-04-10 13:36:12.0 +0200
--- trunk/gcc/tree-vect-slp.c   2013-04-10 15:39:13.865325388 +0200
*** vect_get_and_check_slp_defs (loop_vec_in
*** 376,400 
  }
  
  
! /* Recursively build an SLP tree starting from NODE.
!Fail (and return FALSE) if def-stmts are not isomorphic, require data
!permutation or are of unsupported types of operation.  Otherwise, return
!TRUE.  */
  
  static bool
! vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
!  slp_tree *node, unsigned int group_size,
!  unsigned int *max_nunits,
!  vec *loads,
!  unsigned int vectorization_factor)
  {
unsigned int i;
-   vec stmts = SLP_TREE_SCALAR_STMTS (*node);
gimple stmt = stmts[0];
enum tree_code first_stmt_code = ERROR_MARK, rhs_code = ERROR_MARK;
enum tree_code first_cond_code = ERROR_MARK;
tree lhs;
!   bool stop_recursion = false, need_same_oprnds = false;
tree vectype, scalar_type, first_op1 = NULL_TREE;
optab optab;
int icode;
--- 376,400 
  }
  
  
! /* Verify if the scalar stmts STMTS are isomorphic, require data
!permutation or are of unsupported types of operation.  Return
!true if they are, otherwise return false and indicate in *MATCHES
!which stmts are not isomorphic to the first one.  If MATCHES[0]
!is false then this indicates the comparison could not be
!carried out or the stmts will never be vectorized by SLP.  */
  
  static bool
! vect_build_slp_tree_1 (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
!  vec stmts, unsigned int group_size,
!  unsigned nops, unsigned int *max_nunits,
!  unsigned int vectorization_factor, bool *matches)
  {
unsigned int i;
gimple stmt = stmts[0];
enum tree_code first_stmt_code = ERROR_MARK, rhs_code = ERROR_MARK;
enum tree_code first_cond_code = ERROR_MARK;
tree lhs;
!   bool need_same_oprnds = false;
tree vectype, scalar_type, first_op1 = NULL_TREE;
optab optab;
int icode;
*** vect_build_slp_tree (loop_vec_info loop_
*** 403,429 
struct data_reference *first_dr;
HOST_WIDE_INT dummy;
gimple first_load = NULL, prev_first_load = NULL, old_first_load = NULL;
-   vec oprnds_info;
-   unsigned int nops;
-   slp_oprnd_info oprnd_info;
tree cond;
  
-   if (is_gimple_call (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
- return false;
- 
-   oprnds_info = vect_create_oprnd_info (nops, group_size);
- 
/* For every stmt in NODE find its def stmt/s.  */
FOR_EACH_VEC_ELT (stmts, i, stmt)
  {
if (dump_enabled_p ())
{
  dump_printf_loc (MSG_NOTE, vect_location, "Build SLP for ");
--- 403,415 
struct data_reference *first_dr;
HOST_WIDE_INT dummy;
gimple first_load = NULL, prev_first_load = NULL, old_first_load = NULL;
tree cond;
  
/* For every stmt in NODE find its def stmt/