aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>2018-07-06 22:15:48 +0000
committerKugan Vivekanandarajah <kugan.vivekanandarajah@linaro.org>2018-07-06 22:15:48 +0000
commitbb09b8811111b0422ccc4a5741171c85451533ad (patch)
tree3e6be7f9ff32734c76314abc4064f4fa10c383d2
parentdcf4f8a00a7453121c844f4c2d88fd803c0a5b75 (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@262488 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-16.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-17.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-18.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-19.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/popcount3.c15
-rw-r--r--gcc/tree-ssa-phiopt.c136
8 files changed, 217 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 10137d6b411..648bb3ab673 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 541fafb9960..c7f240ec4fb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+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
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-16.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-16.c
new file mode 100644
index 00000000000..e7a271150f8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-16.c
@@ -0,0 +1,12 @@
+/* { 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" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-17.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-17.c
new file mode 100644
index 00000000000..25ba096cd8e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-17.c
@@ -0,0 +1,12 @@
+/* { 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" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-18.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-18.c
new file mode 100644
index 00000000000..cf1aaf5c568
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-18.c
@@ -0,0 +1,14 @@
+/* { 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" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-19.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-19.c
new file mode 100644
index 00000000000..1f440660de0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-19.c
@@ -0,0 +1,15 @@
+/* { 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" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/popcount3.c b/gcc/testsuite/gcc.dg/tree-ssa/popcount3.c
new file mode 100644
index 00000000000..8a900896e50
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/popcount3.c
@@ -0,0 +1,15 @@
+/* { 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" } } */
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 8e94f6a999a..b2575f1281a 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -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.