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> 2018-07-06 Kugan Vivekanandarajah <kuganv@linaro.org>
* tree-ssa-loop-niter.c (number_of_iterations_popcount): If popcount * 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> 2018-07-06 Kugan Vivekanandarajah <kuganv@linaro.org>
* gcc.dg/tree-ssa/pr64183.c: Disable final value replacement * 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 ...@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-scalar-evolution.h" #include "tree-scalar-evolution.h"
#include "tree-inline.h" #include "tree-inline.h"
#include "params.h" #include "params.h"
#include "case-cfn-macros.h"
static unsigned int tree_ssa_phiopt_worker (bool, bool); static unsigned int tree_ssa_phiopt_worker (bool, bool);
static bool conditional_replacement (basic_block, basic_block, static bool conditional_replacement (basic_block, basic_block,
...@@ -57,6 +58,8 @@ static bool minmax_replacement (basic_block, basic_block, ...@@ -57,6 +58,8 @@ static bool minmax_replacement (basic_block, basic_block,
edge, edge, gimple *, tree, tree); edge, edge, gimple *, tree, tree);
static bool abs_replacement (basic_block, basic_block, static bool abs_replacement (basic_block, basic_block,
edge, edge, gimple *, tree, tree); 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, static bool cond_store_replacement (basic_block, basic_block, edge, edge,
hash_set<tree> *); hash_set<tree> *);
static bool cond_if_else_store_replacement (basic_block, basic_block, basic_block); 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) ...@@ -332,6 +335,9 @@ tree_ssa_phiopt_worker (bool do_store_elim, bool do_hoist_loads)
cfgchanged = true; cfgchanged = true;
else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1)) else if (abs_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
cfgchanged = true; 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)) else if (minmax_replacement (bb, bb1, e1, e2, phi, arg0, arg1))
cfgchanged = true; cfgchanged = true;
} }
...@@ -1517,6 +1523,136 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb, ...@@ -1517,6 +1523,136 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
return true; 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 /* The function absolute_replacement does the main work of doing the absolute
replacement. Return true if the replacement is done. Otherwise return replacement. Return true if the replacement is done. Otherwise return
false. 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