re PR tree-optimization/66623 (Unsafe FP math reduction used in strict math mode)
authorRichard Biener <rguenther@suse.de>
Fri, 9 Jun 2017 09:40:45 +0000 (09:40 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 9 Jun 2017 09:40:45 +0000 (09:40 +0000)
2017-06-09  Richard Biener  <rguenther@suse.de>

PR tree-optimization/66623
* tree-vect-loop.c (vect_is_simple_reduction): Cleanup,
refactor check_reduction into two parts, properly computing
whether we have to check reduction validity for outer loop
vectorization.

* gcc.dg/vect/pr66623.c: New testcase.

From-SVN: r249053

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/pr66623.c [new file with mode: 0644]
gcc/tree-vect-loop.c

index e40383303dc287ea1131f0eef156c5fd461d2f85..05e6fbfdbdbc7204a8f88ef20e31a9a94e813f96 100644 (file)
@@ -1,3 +1,11 @@
+2017-06-09  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/66623
+       * tree-vect-loop.c (vect_is_simple_reduction): Cleanup,
+       refactor check_reduction into two parts, properly computing
+       whether we have to check reduction validity for outer loop
+       vectorization.
+
 2017-06-09  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/79483
index 967ca018d718e2262c22bb791175c8cd6f0fb33f..7bef1b5435ee3d7fe2bce1b07e99f34f4145169b 100644 (file)
@@ -1,3 +1,8 @@
+2017-06-09  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/66623
+       * gcc.dg/vect/pr66623.c: New testcase.
+
 2017-06-09  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/79483
diff --git a/gcc/testsuite/gcc.dg/vect/pr66623.c b/gcc/testsuite/gcc.dg/vect/pr66623.c
new file mode 100644 (file)
index 0000000..f90c673
--- /dev/null
@@ -0,0 +1,86 @@
+/* { dg-require-effective-target vect_float } */
+
+#include "tree-vect.h"
+
+extern void abort (void);
+
+#define OP *
+#define INIT 1.0
+
+float __attribute__((noinline,noclone))
+foo (float *__restrict__ i)
+{
+  float l = INIT;
+  int a;
+  int b;
+
+  for (a = 0; a < 4; a++)
+    for (b = 0; b < 4; b++)
+      l = l OP i[b];
+
+  return l;
+}
+
+float __attribute__((noinline,noclone))
+foo_ref (float *__restrict__ i)
+{
+  float l = INIT;
+
+  l = l OP i[0];
+  l = l OP i[1];
+  l = l OP i[2];
+  l = l OP i[3];
+
+  l = l OP i[0];
+  l = l OP i[1];
+  l = l OP i[2];
+  l = l OP i[3];
+
+  l = l OP i[0];
+  l = l OP i[1];
+  l = l OP i[2];
+  l = l OP i[3];
+
+  l = l OP i[0];
+  l = l OP i[1];
+  l = l OP i[2];
+  l = l OP i[3];
+
+  return l;
+}
+
+union u
+{
+  float f;
+  unsigned int u;
+};
+
+int
+main (void)
+{
+  union u res, res2;
+  float a[4];
+
+  if (sizeof (float) != sizeof (unsigned int))
+    return 0;
+
+  check_vect ();
+
+  a[0] = 0.01;
+  a[1] = 0.01;
+  a[2] = 0.01;
+  a[3] = 1.0;
+
+  res.f = foo_ref (a);
+
+  res2.f = foo (a);
+
+  if (res.u != res2.u)
+    abort ();
+
+  return 0;
+}
+
+/* need -ffast-math to vectorize this loop.  */
+/* ARM NEON passes -ffast-math to these tests, so expect this to fail.  */
+/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" { xfail arm_neon_ok } } } */
index 92d9a28fd9a998c981e3351ef48f869392893b79..64cf05dea577b139162289707c0ff224f12ea3ef 100644 (file)
@@ -2727,8 +2727,6 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
 {
   struct loop *loop = (gimple_bb (phi))->loop_father;
   struct loop *vect_loop = LOOP_VINFO_LOOP (loop_info);
-  edge latch_e = loop_latch_edge (loop);
-  tree loop_arg = PHI_ARG_DEF_FROM_EDGE (phi, latch_e);
   gimple *def_stmt, *def1 = NULL, *def2 = NULL, *phi_use_stmt = NULL;
   enum tree_code orig_code, code;
   tree op1, op2, op3 = NULL_TREE, op4 = NULL_TREE;
@@ -2742,11 +2740,6 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
   *double_reduc = false;
   *v_reduc_type = TREE_CODE_REDUCTION;
 
-  /* Check validity of the reduction only for the innermost loop.  */
-  bool check_reduction = ! flow_loop_nested_p (vect_loop, loop);
-  gcc_assert ((check_reduction && loop == vect_loop)
-              || (!check_reduction && flow_loop_nested_p (vect_loop, loop)));
-
   name = PHI_RESULT (phi);
   /* ???  If there are no uses of the PHI result the inner loop reduction
      won't be detected as possibly double-reduction by vectorizable_reduction
@@ -2775,13 +2768,15 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
         {
           if (dump_enabled_p ())
            dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-                            "reduction used in loop.\n");
+                            "reduction value used in loop.\n");
           return NULL;
         }
 
       phi_use_stmt = use_stmt;
     }
 
+  edge latch_e = loop_latch_edge (loop);
+  tree loop_arg = PHI_ARG_DEF_FROM_EDGE (phi, latch_e);
   if (TREE_CODE (loop_arg) != SSA_NAME)
     {
       if (dump_enabled_p ())
@@ -2795,18 +2790,22 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
     }
 
   def_stmt = SSA_NAME_DEF_STMT (loop_arg);
-  if (!def_stmt)
+  if (gimple_nop_p (def_stmt))
     {
       if (dump_enabled_p ())
        dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-                        "reduction: no def_stmt.\n");
+                        "reduction: no def_stmt\n");
       return NULL;
     }
 
   if (!is_gimple_assign (def_stmt) && gimple_code (def_stmt) != GIMPLE_PHI)
     {
       if (dump_enabled_p ())
-       dump_gimple_stmt (MSG_NOTE, TDF_SLIM, def_stmt, 0);
+       {
+         dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+                          "reduction: unhandled reduction operation: ");
+         dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM, def_stmt, 0);
+       }
       return NULL;
     }
 
@@ -2822,6 +2821,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
     }
 
   nloop_uses = 0;
+  auto_vec<gphi *, 3> lcphis;
   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, name)
     {
       gimple *use_stmt = USE_STMT (use_p);
@@ -2829,6 +2829,9 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
        continue;
       if (flow_bb_inside_loop_p (loop, gimple_bb (use_stmt)))
        nloop_uses++;
+      else
+       /* We can have more than one loop-closed PHI.  */
+       lcphis.safe_push (as_a <gphi *> (use_stmt));
       if (nloop_uses > 1)
        {
          if (dump_enabled_p ())
@@ -2873,6 +2876,27 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
       return NULL;
     }
 
+  /* If we are vectorizing an inner reduction we are executing that
+     in the original order only in case we are not dealing with a
+     double reduction.  */
+  bool check_reduction = true;
+  if (flow_loop_nested_p (vect_loop, loop))
+    {
+      gphi *lcphi;
+      unsigned i;
+      check_reduction = false;
+      FOR_EACH_VEC_ELT (lcphis, i, lcphi)
+       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_phi_result (lcphi))
+         {
+           gimple *use_stmt = USE_STMT (use_p);
+           if (is_gimple_debug (use_stmt))
+             continue;
+           if (! flow_bb_inside_loop_p (vect_loop, gimple_bb (use_stmt)))
+             check_reduction = true;
+         }
+    }
+
+  bool nested_in_vect_loop = flow_loop_nested_p (vect_loop, loop);
   code = orig_code = gimple_assign_rhs_code (def_stmt);
 
   /* We can handle "res -= x[i]", which is non-associative by
@@ -2887,27 +2911,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
 
   if (code == COND_EXPR)
     {
-      if (check_reduction)
+      if (! nested_in_vect_loop)
        *v_reduc_type = COND_REDUCTION;
-    }
-  else if (!commutative_tree_code (code) || !associative_tree_code (code))
-    {
-      if (dump_enabled_p ())
-       report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
-                       "reduction: not commutative/associative: ");
-      return NULL;
-    }
-
-  if (get_gimple_rhs_class (code) != GIMPLE_BINARY_RHS)
-    {
-      if (code != COND_EXPR)
-        {
-         if (dump_enabled_p ())
-           report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
-                           "reduction: not binary operation: ");
-
-          return NULL;
-        }
 
       op3 = gimple_assign_rhs1 (def_stmt);
       if (COMPARISON_CLASS_P (op3))
@@ -2918,30 +2923,35 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
 
       op1 = gimple_assign_rhs2 (def_stmt);
       op2 = gimple_assign_rhs3 (def_stmt);
-
-      if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME)
-        {
-          if (dump_enabled_p ())
-            report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
-                           "reduction: uses not ssa_names: ");
-
-          return NULL;
-        }
     }
-  else
+  else if (!commutative_tree_code (code) || !associative_tree_code (code))
+    {
+      if (dump_enabled_p ())
+       report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
+                       "reduction: not commutative/associative: ");
+      return NULL;
+    }
+  else if (get_gimple_rhs_class (code) == GIMPLE_BINARY_RHS)
     {
       op1 = gimple_assign_rhs1 (def_stmt);
       op2 = gimple_assign_rhs2 (def_stmt);
+    }
+  else
+    {
+      if (dump_enabled_p ())
+       report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
+                       "reduction: not handled operation: ");
+      return NULL;
+    }
 
-      if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME)
-        {
-          if (dump_enabled_p ())
-           report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
-                           "reduction: uses not ssa_names: ");
+  if (TREE_CODE (op1) != SSA_NAME && TREE_CODE (op2) != SSA_NAME)
+    {
+      if (dump_enabled_p ())
+       report_vect_op (MSG_MISSED_OPTIMIZATION, def_stmt,
+                       "reduction: both uses not ssa_names: ");
 
-          return NULL;
-        }
-   }
+      return NULL;
+    }
 
   type = TREE_TYPE (gimple_assign_lhs (def_stmt));
   if ((TREE_CODE (op1) == SSA_NAME
@@ -3091,7 +3101,7 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
                           == vect_internal_def
                      && !is_loop_header_bb_p (gimple_bb (def2)))))))
     {
-      if (check_reduction && orig_code != MINUS_EXPR)
+      if (! nested_in_vect_loop && orig_code != MINUS_EXPR)
        {
          /* Check if we can swap operands (just for simplicity - so that
             the rest of the code can assume that the reduction variable
@@ -3145,7 +3155,8 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
     }
 
   /* Try to find SLP reduction chain.  */
-  if (check_reduction && code != COND_EXPR
+  if (! nested_in_vect_loop
+      && code != COND_EXPR
       && vect_is_slp_reduction (loop_info, phi, def_stmt))
     {
       if (dump_enabled_p ())