diff options
author | amker <amker@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-04-20 15:57:01 +0000 |
---|---|---|
committer | amker <amker@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-04-20 15:57:01 +0000 |
commit | 4bd8a05996c70153e47a55bf6aadd79d2ebef0ef (patch) | |
tree | 7b075215f21e6c36021bf238f66fc504b4709773 | |
parent | 9703b7603e5293bacd3d693ff0d438b2a9c3e779 (diff) | |
download | gcc-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/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ifc-pr69489-2.c | 17 | ||||
-rw-r--r-- | gcc/tree-if-conv.c | 68 |
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) |