Commit 58f12ec1 by Kugan Vivekanandarajah Committed by Kugan Vivekanandarajah

tree-ssa-phiopt.c (cond_removal_in_popcount_pattern): New.

gcc/ChangeLog:

2018-07-06  Kugan Vivekanandarajah  <kugan.vivekanandarajah@linaro.org>

	* tree-ssa-phiopt.c (cond_removal_in_popcount_pattern): New.
	(tree_ssa_phiopt_worker): Call cond_removal_in_popcount_pattern.

gcc/testsuite/ChangeLog:

2018-07-06  Kugan Vivekanandarajah  <kugan.vivekanandarajah@linaro.org>

	* gcc.dg/tree-ssa/phi-opt-16.c: New test.
	* gcc.dg/tree-ssa/phi-opt-17.c: New test.
	* gcc.dg/tree-ssa/phi-opt-18.c: New test.
	* gcc.dg/tree-ssa/phi-opt-19.c: New test.
	* gcc.dg/tree-ssa/popcount3.c: New test.

From-SVN: r262488
parent b8b31957
2018-07-06 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
* tree-ssa-phiopt.c (cond_removal_in_popcount_pattern): New.
(tree_ssa_phiopt_worker): Call cond_removal_in_popcount_pattern.
2018-07-06 Kugan Vivekanandarajah <kuganv@linaro.org>
* tree-ssa-loop-niter.c (number_of_iterations_popcount): If popcount
......
2018-07-06 Kugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>
* gcc.dg/tree-ssa/phi-opt-16.c: New test.
* gcc.dg/tree-ssa/phi-opt-17.c: New test.
* gcc.dg/tree-ssa/phi-opt-18.c: New test.
* gcc.dg/tree-ssa/phi-opt-19.c: New test.
* gcc.dg/tree-ssa/popcount3.c: New test.
2018-07-06 Kugan Vivekanandarajah <kuganv@linaro.org>
* gcc.dg/tree-ssa/pr64183.c: Disable final value replacement
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
int foo (int a)
{
int c = 0;
if (a != 0)
c = __builtin_popcount (a);
return c;
}
/* { dg-final { scan-tree-dump-not "if" "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
int foo (unsigned int a)
{
int c = 0;
if (a != 0)
c = __builtin_popcount (a);
return c;
}
/* { dg-final { scan-tree-dump-not "if" "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized" } */
int foo (int a)
{
int c = 0;
if (a != 0)
c = __builtin_popcount (a);
else
c = 1;
return c;
}
/* { dg-final { scan-tree-dump-times "if " 1 "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-optimized -fno-tree-dce" } */
int foo (int a)
{
int c = 0;
if (a != 0)
{
__builtin_popcount (a);
c = 2;
}
return c;
}
/* { dg-final { scan-tree-dump-times "if " 1 "optimized" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-phiopt3 -fdump-tree-optimized" } */
int PopCount (long b) {
int c = 0;
while (b) {
b &= b - 1;
c++;
}
return c;
}
/* { dg-final { scan-tree-dump-times "__builtin_popcount" 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "if" 0 "phiopt3" } } */
......@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h"
#include "tree-inline.h"
#include "params.h"
#include "case-cfn-macros.h"
static unsigned int tree_ssa_phiopt_worker (bool, bool);
static bool conditional_replacement (basic_block, basic_block,
......@@ -57,6 +58,8 @@ static bool minmax_replacement (basic_block, basic_block,
edge, edge, gimple *, tree, tree);
static bool abs_replacement (basic_block, basic_block,
edge, edge, gimple *, tree, tree);
static bool cond_removal_in_popcount_pattern (basic_block, basic_block,
edge, edge, gimple *, tree, tree);
static bool cond_store_replacement (basic_block, basic_block, edge, edge,
hash_set<tree> *);
static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block);
......@@ -332,6 +335,9 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
cfgchanged = true;
else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
cfgchanged = true;
else if (cond_removal_in_popcount_pattern (bb, bb1, e1, e2,
phi, arg0, arg1))
cfgchanged = true;
else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
cfgchanged = true;
}
......@@ -1517,6 +1523,136 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
return true;
}
/* Convert
<bb 2>
if (b_4(D) != 0)
goto <bb 3>
else
goto <bb 4>
<bb 3>
_2 = (unsigned long) b_4(D);
_9 = __builtin_popcountl (_2);
OR
_9 = __builtin_popcountl (b_4(D));
<bb 4>
c_12 = PHI <0(2), _9(3)>
Into
<bb 2>
_2 = (unsigned long) b_4(D);
_9 = __builtin_popcountl (_2);
OR
_9 = __builtin_popcountl (b_4(D));
<bb 4>
c_12 = PHI <_9(2)>
*/
static bool
cond_removal_in_popcount_pattern (basic_block cond_bb, basic_block middle_bb,
edge e1, edge e2,
gimple *phi, tree arg0, tree arg1)
{
gimple *cond;
gimple_stmt_iterator gsi, gsi_from;
gimple *popcount;
gimple *cast = NULL;
tree lhs, arg;
/* Check that
_2 = (unsigned long) b_4(D);
_9 = __builtin_popcountl (_2);
OR
_9 = __builtin_popcountl (b_4(D));
are the only stmts in the middle_bb. */
gsi = gsi_start_nondebug_after_labels_bb (middle_bb);
if (gsi_end_p (gsi))
return false;
cast = gsi_stmt (gsi);
gsi_next_nondebug (&gsi);
if (!gsi_end_p (gsi))
{
popcount = gsi_stmt (gsi);
gsi_next_nondebug (&gsi);
if (!gsi_end_p (gsi))
return false;
}
else
{
popcount = cast;
cast = NULL;
}
/* Check that we have a popcount builtin. */
if (!is_gimple_call (popcount))
return false;
combined_fn cfn = gimple_call_combined_fn (popcount);
switch (cfn)
{
CASE_CFN_POPCOUNT:
break;
default:
return false;
}
arg = gimple_call_arg (popcount, 0);
lhs = gimple_get_lhs (popcount);
if (cast)
{
/* We have a cast stmt feeding popcount builtin. */
/* Check that we have a cast prior to that. */
if (gimple_code (cast) != GIMPLE_ASSIGN
|| !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (cast)))
return false;
/* Result of the cast stmt is the argument to the builtin. */
if (arg != gimple_assign_lhs (cast))
return false;
arg = gimple_assign_rhs1 (cast);
}
/* Canonicalize. */
if (e2->flags & EDGE_TRUE_VALUE)
{
std::swap (arg0, arg1);
std::swap (e1, e2);
}
/* Check PHI arguments. */
if (lhs != arg0 || !integer_zerop (arg1))
return false;
cond = last_stmt (cond_bb);
/* Cond_bb has a check for b_4 != 0 before calling the popcount
builtin. */
if (gimple_code (cond) != GIMPLE_COND
|| gimple_cond_code (cond) != NE_EXPR
|| !integer_zerop (gimple_cond_rhs (cond))
|| arg != gimple_cond_lhs (cond))
return false;
/* And insert the popcount builtin and cast stmt before the cond_bb. */
gsi = gsi_last_bb (cond_bb);
if (cast)
{
gsi_from = gsi_for_stmt (cast);
gsi_move_before (&gsi_from, &gsi);
reset_flow_sensitive_info (gimple_get_lhs (cast));
}
gsi_from = gsi_for_stmt (popcount);
gsi_move_before (&gsi_from, &gsi);
reset_flow_sensitive_info (gimple_get_lhs (popcount));
/* Now update the PHI and remove unneeded bbs. */
replace_phi_edge_with_variable (cond_bb, e2, phi, lhs);
return true;
}
/* The function absolute_replacement does the main work of doing the absolute
replacement. Return true if the replacement is done. Otherwise return
false.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment