re PR tree-optimization/69489 (missed vectorization for boolean loop, missed if-conve...
authorBin Cheng <bin.cheng@arm.com>
Wed, 20 Apr 2016 15:57:01 +0000 (15:57 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Wed, 20 Apr 2016 15:57:01 +0000 (15:57 +0000)
PR tree-optimization/69489
* tree-if-conv.c (phi_convertible_by_degenerating_args): New.
(if_convertible_phi_p): Call phi_convertible_by_degenerating_args.
Revise dump message.
(if_convertible_bb_p): Remove check on edge count of basic block's
predecessors.

gcc/testsuite/ChangeLog
PR tree-optimization/69489
* gcc.dg/tree-ssa/ifc-pr69489-2.c: New test.

From-SVN: r235292

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ifc-pr69489-2.c [new file with mode: 0644]
gcc/tree-if-conv.c

index 1f3d66b24de98cb7265425e9573c3f33d4fd37d2..55d9708336bf72683487f047915ab60291959e73 100644 (file)
@@ -1,3 +1,12 @@
+2016-04-20  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/69489
+       * tree-if-conv.c (phi_convertible_by_degenerating_args): New.
+       (if_convertible_phi_p): Call phi_convertible_by_degenerating_args.
+       Revise dump message.
+       (if_convertible_bb_p): Remove check on edge count of basic block's
+       predecessors.
+
 2016-04-20  Bin Cheng  <bin.cheng@arm.com>
 
        PR tree-optimization/56625
index bf59b9b180271e7c5288f7bacf7e56c3996c1c86..57f5bb4a8e39a60a57a60e11a8b00ec1a86b3171 100644 (file)
@@ -1,3 +1,8 @@
+2016-04-20  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/69489
+       * gcc.dg/tree-ssa/ifc-pr69489-2.c: New test.
+
 2016-04-20  Ilya Verbin  <ilya.verbin@intel.com>
 
        PR c++/69363
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr69489-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr69489-2.c
new file mode 100644 (file)
index 0000000..6661f1a
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-S -O2 -ftree-vectorize -fdump-tree-ifcvt-stats" { target *-*-* } } */
+
+double
+foo (const char *u, const char *v, long n)
+{
+  long i, n1 = 0, n2 = 0;
+
+  for (i = 0; i < n; i++)
+    {
+      n2 += (u[i] && !v[i]);
+      n1 += (!u[i] && v[i]);
+    }
+  return (2.0 * n2 * n1);
+}
+
+/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */
index 691811322f71e81c842bbfd63255e7f3f86bf072..04a1d3e536db27591c09f7e3d785358e5bd5895c 100644 (file)
@@ -575,6 +575,65 @@ bb_with_exit_edge_p (struct loop *loop, basic_block bb)
   return false;
 }
 
+/* Given PHI which has more than two arguments, this function checks if
+   it's if-convertible by degenerating its arguments.  Specifically, if
+   below two conditions are satisfied:
+
+     1) Number of PHI arguments with different values equals to 2 and one
+       argument has the only occurrence.
+     2) The edge corresponding to the unique argument isn't critical edge.
+
+   Such PHI can be handled as PHIs have only two arguments.  For example,
+   below PHI:
+
+     res = PHI <A_1(e1), A_1(e2), A_2(e3)>;
+
+   can be transformed into:
+
+     res = (predicate of e3) ? A_2 : A_1;
+
+   Return TRUE if it is the case, FALSE otherwise.  */
+
+static bool
+phi_convertible_by_degenerating_args (gphi *phi)
+{
+  edge e;
+  tree arg, t1 = NULL, t2 = NULL;
+  unsigned int i, i1 = 0, i2 = 0, n1 = 0, n2 = 0;
+  unsigned int num_args = gimple_phi_num_args (phi);
+
+  gcc_assert (num_args > 2);
+
+  for (i = 0; i < num_args; i++)
+    {
+      arg = gimple_phi_arg_def (phi, i);
+      if (t1 == NULL || operand_equal_p (t1, arg, 0))
+       {
+         n1++;
+         i1 = i;
+         t1 = arg;
+       }
+      else if (t2 == NULL || operand_equal_p (t2, arg, 0))
+       {
+         n2++;
+         i2 = i;
+         t2 = arg;
+       }
+      else
+       return false;
+    }
+
+  if (n1 != 1 && n2 != 1)
+    return false;
+
+  /* Check if the edge corresponding to the unique arg is critical.  */
+  e = gimple_phi_arg_edge (phi, (n1 == 1) ? i1 : i2);
+  if (EDGE_COUNT (e->src->succs) > 1)
+    return false;
+
+  return true;
+}
+
 /* Return true when PHI is if-convertible.  PHI is part of loop LOOP
    and it belongs to basic block BB.
 
@@ -601,10 +660,11 @@ if_convertible_phi_p (struct loop *loop, basic_block bb, gphi *phi,
   if (bb != loop->header)
     {
       if (gimple_phi_num_args (phi) != 2
-         && !aggressive_if_conv)
+         && !aggressive_if_conv
+         && !phi_convertible_by_degenerating_args (phi))
        {
          if (dump_file && (dump_flags & TDF_DETAILS))
-           fprintf (dump_file, "More than two phi node args.\n");
+           fprintf (dump_file, "Phi can't be predicated by single cond.\n");
          return false;
         }
     }
@@ -1003,10 +1063,6 @@ if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb)
   if (EDGE_COUNT (bb->succs) > 2)
     return false;
 
-  if (EDGE_COUNT (bb->preds) > 2
-      && !aggressive_if_conv)
-    return false;
-
   if (exit_bb)
     {
       if (bb != loop->latch)