summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoramker <amker@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-20 15:57:01 +0000
committeramker <amker@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-20 15:57:01 +0000
commit4bd8a05996c70153e47a55bf6aadd79d2ebef0ef (patch)
tree7b075215f21e6c36021bf238f66fc504b4709773
parent9703b7603e5293bacd3d693ff0d438b2a9c3e779 (diff)
downloadgcc-4bd8a05996c70153e47a55bf6aadd79d2ebef0ef.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235292 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ifc-pr69489-2.c17
-rw-r--r--gcc/tree-if-conv.c68
4 files changed, 93 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1f3d66b24de..55d9708336b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
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
PR tree-optimization/69489
* tree-data-ref.h (DR_INNERMOST): New macro.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bf59b9b1802..57f5bb4a8e3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..6661f1a6c1b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr69489-2.c
@@ -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" } } */
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 691811322f7..04a1d3e536d 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -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)