This fixes PR56157 - when looking up operands for a vectorized
SLP stmt we have to match up SLP childs with operands.  We do
so by looking for the operand in the DEF position of the SLP
child.  But that get's complicated in face of either stmt being
a pattern stmt and its operands being DEFed by pattern stmts
(in case this is a multiple stmt pattern) or by the scalar
variant (of eventually another pattern the SLP child points to).

I ended up giving up trying to be clever and trying to handle all
situations with a single compare and just compare with pattern
and non-pattern def.  False matches are not possible, just we
must not miss a match.

Bootstrapped and tested on x86_64-unknown-linux-gnu, ok?

Thanks,
Richard.

2013-01-31  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/
        * tree-vect-slp.c (vect_get_slp_defs): More thoroughly try to
        match up operand with SLP child.

        * gcc.dg/torture/pr56157.c: New testcase.

Index: gcc/tree-vect-slp.c
===================================================================
*** gcc/tree-vect-slp.c (revision 195610)
--- gcc/tree-vect-slp.c (working copy)
*************** void
*** 2616,2628 ****
  vect_get_slp_defs (vec<tree> ops, slp_tree slp_node,
                     vec<slp_void_p> *vec_oprnds, int reduc_index)
  {
!   gimple first_stmt, first_def;
    int number_of_vects = 0, i;
    unsigned int child_index = 0;
    HOST_WIDE_INT lhs_size_unit, rhs_size_unit;
    slp_tree child = NULL;
    vec<tree> *vec_defs;
!   tree oprnd, def_lhs;
    bool vectorized_defs;
  
    first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0];
--- 2616,2628 ----
  vect_get_slp_defs (vec<tree> ops, slp_tree slp_node,
                     vec<slp_void_p> *vec_oprnds, int reduc_index)
  {
!   gimple first_stmt;
    int number_of_vects = 0, i;
    unsigned int child_index = 0;
    HOST_WIDE_INT lhs_size_unit, rhs_size_unit;
    slp_tree child = NULL;
    vec<tree> *vec_defs;
!   tree oprnd;
    bool vectorized_defs;
  
    first_stmt = SLP_TREE_SCALAR_STMTS (slp_node)[0];
*************** vect_get_slp_defs (vec<tree> ops, slp_tr
*** 2638,2666 ****
        if (SLP_TREE_CHILDREN (slp_node).length () > child_index)
          {
            child = (slp_tree) SLP_TREE_CHILDREN (slp_node)[child_index];
-           first_def = SLP_TREE_SCALAR_STMTS (child)[0];
  
!         /* In the end of a pattern sequence we have a use of the original 
stmt,
!            so we need to compare OPRND with the original def.  */
!           if (is_pattern_stmt_p (vinfo_for_stmt (first_def))
!             && !STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (first_stmt))
!               && !is_pattern_stmt_p (vinfo_for_stmt (first_stmt)))
!             first_def = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (first_def));
  
!           if (is_gimple_call (first_def))
!             def_lhs = gimple_call_lhs (first_def);
!           else
!             def_lhs = gimple_assign_lhs (first_def);
! 
!           if (operand_equal_p (oprnd, def_lhs, 0))
!             {
!               /* The number of vector defs is determined by the number of
!                  vector statements in the node from which we get those
                 statements.  */
!                  number_of_vects = SLP_TREE_NUMBER_OF_VEC_STMTS (child);
!                  vectorized_defs = true;
              child_index++;
!             }
          }
  
        if (!vectorized_defs)
--- 2638,2659 ----
        if (SLP_TREE_CHILDREN (slp_node).length () > child_index)
          {
            child = (slp_tree) SLP_TREE_CHILDREN (slp_node)[child_index];
  
!         /* We have to check both pattern and original def, if available.  */
!         gimple first_def = SLP_TREE_SCALAR_STMTS (child)[0];
!         gimple related = STMT_VINFO_RELATED_STMT (vinfo_for_stmt (first_def));
  
!         if (operand_equal_p (oprnd, gimple_get_lhs (first_def), 0)
!             || (related
!                 && operand_equal_p (oprnd, gimple_get_lhs (related), 0)))
!           {
!             /* The number of vector defs is determined by the number of
!                vector statements in the node from which we get those
                 statements.  */
!             number_of_vects = SLP_TREE_NUMBER_OF_VEC_STMTS (child);
!             vectorized_defs = true;
              child_index++;
!           }
          }
  
        if (!vectorized_defs)
Index: gcc/testsuite/gcc.dg/torture/pr56157.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr56157.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr56157.c      (working copy)
***************
*** 0 ****
--- 1,25 ----
+ /* { dg-do compile } */
+ /* { dg-options "-ftree-vectorize" } */
+ 
+ struct Pixel {
+     unsigned short r;
+     unsigned short g;
+     unsigned short b;
+     unsigned short a;
+ };
+ 
+ void fn(unsigned char * __restrict dst, const unsigned char * __restrict src)
+ {
+   unsigned x;
+   for(x = 0; x < 1024; x += 1)
+     {
+       struct Pixel pixel;
+       pixel.r = (unsigned short)(((unsigned)src[0]) * 0xffff / 0xff);
+       pixel.g = (unsigned short)(((unsigned)src[1]) * 0xffff / 0xff);
+       pixel.b = (unsigned short)(((unsigned)src[2]) * 0xffff / 0xff);
+       pixel.a = (unsigned short)(((unsigned)src[3]) * 0xffff / 0xff);
+       __builtin_memcpy(dst, &pixel, sizeof pixel);
+       src += 4;
+       dst += 8;
+     }
+ }

Reply via email to