re PR tree-optimization/69489 (missed vectorization for boolean loop, missed if-conversion)

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
This commit is contained in:
Bin Cheng 2016-04-20 15:57:01 +00:00 committed by Bin Cheng
parent 4986f823a2
commit 1011119f47
4 changed files with 93 additions and 6 deletions

View 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

View 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

View File

@ -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" } } */

View 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)