The following fixes PR81571.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied.

Richard.

2017-07-27  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/81571
        * tree-vect-slp.c (vect_build_slp_tree): Properly verify reduction
        PHIs.

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

Index: gcc/tree-vect-slp.c
===================================================================
--- gcc/tree-vect-slp.c (revision 250607)
+++ gcc/tree-vect-slp.c (working copy)
@@ -947,11 +948,27 @@ vect_build_slp_tree (vec_info *vinfo,
      the recursion.  */
   if (gimple_code (stmt) == GIMPLE_PHI)
     {
+      vect_def_type def_type = STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt));
       /* Induction from different IVs is not supported.  */
-      if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt)) == vect_induction_def)
-       FOR_EACH_VEC_ELT (stmts, i, stmt)
-         if (stmt != stmts[0])
-           return NULL;
+      if (def_type == vect_induction_def)
+       {
+         FOR_EACH_VEC_ELT (stmts, i, stmt)
+           if (stmt != stmts[0])
+             return NULL;
+       }
+      else
+       {
+         /* Else def types have to match.  */
+         FOR_EACH_VEC_ELT (stmts, i, stmt)
+           {
+             /* But for reduction chains only check on the first stmt.  */
+             if (GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt))
+                 && GROUP_FIRST_ELEMENT (vinfo_for_stmt (stmt)) != stmt)
+               continue;
+             if (STMT_VINFO_DEF_TYPE (vinfo_for_stmt (stmt)) != def_type)
+               return NULL;
+           }
+       }
       node = vect_create_new_slp_node (stmts);
       return node;
     }
Index: gcc/testsuite/gcc.dg/torture/pr81571.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr81571.c      (nonexistent)
+++ gcc/testsuite/gcc.dg/torture/pr81571.c      (working copy)
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+int a, b, c, d;
+short fn1(int p1, int p2) { return p1; }
+
+int fn2(int p1) {}
+
+int main()
+{
+  for (; c; c++)
+    a |= fn1(1, a) | fn2(b |= d);
+  return 0;
+}

Reply via email to