[PATCH 3/6] ccmp: Reject chains without an explicit comparison [PR109832]

<[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>
From: Kyrylo Tkachov <[email protected]>

The conditional-compare expander accepts a plain boolean as a comparison
against zero.  This is useful when a chain also contains an explicit
comparison.  It is harmful when every leaf is a boolean.  For example:

  _Bool
  f (_Bool x, _Bool y)
  {
    return x || y;
  }

AArch64 emitted:

	and	w1, w1, 255
	tst	w0, 255
	ccmp	w1, 0, 0, eq
	cset	w0, ne

After this patch it emits one bitwise operation:

	orr	w0, w0, w1

Require at least one explicit comparison in a conditional-compare tree.
Mixed boolean and comparison chains remain accepted.

Bootstrapped and tested on aarch64-none-linux-gnu.
Ok for trunk?
Thanks,
Kyrill

gcc/

	PR middle-end/109832
	* ccmp.cc (ccmp_tree_has_comparison_p): New function.
	(expand_ccmp_expr): Reject an all-boolean tree.

gcc/testsuite/

	PR middle-end/109832
	* gcc.target/aarch64/ccmp_7.c: New test.

Signed-off-by: Kyrylo Tkachov <[email protected]>
---
 gcc/ccmp.cc                               | 24 ++++++++++++
 gcc/testsuite/gcc.target/aarch64/ccmp_7.c | 46 +++++++++++++++++++++++
 2 files changed, 70 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/ccmp_7.c

diff --git a/gcc/ccmp.cc b/gcc/ccmp.cc
index 1c540f641b2..9f7670bf58e 100644
--- a/gcc/ccmp.cc
+++ b/gcc/ccmp.cc
@@ -93,6 +93,25 @@ ccmp_tree_comparison_p (tree t, basic_block bb)
 
 typedef hash_map<tree, bool> ccmp_uniform_cache;
 
+/* Return true if AND/IOR tree T contains a comparison in BB.  */
+
+static bool
+ccmp_tree_has_comparison_p (tree t, basic_block bb)
+{
+  gimple *g = get_gimple_for_ssa_name (t);
+  if (!g || !is_gimple_assign (g))
+    return false;
+
+  tree_code code = gimple_assign_rhs_code (g);
+  if (TREE_CODE_CLASS (code) == tcc_comparison)
+    return gimple_bb (g) == bb;
+  if (code != BIT_AND_EXPR && code != BIT_IOR_EXPR)
+    return false;
+
+  return (ccmp_tree_has_comparison_p (gimple_assign_rhs1 (g), bb)
+	  || ccmp_tree_has_comparison_p (gimple_assign_rhs2 (g), bb));
+}
+
 /* Return true if T is a CODE tree in BB whose leaves are comparisons.
    CACHE records results for logical SSA definitions.  */
 
@@ -368,6 +387,11 @@ expand_ccmp_expr (gimple *g, machine_mode mode)
   if (!ccmp_candidate_p (g, cache, true))
     return NULL_RTX;
 
+  basic_block bb = gimple_bb (g);
+  if (!ccmp_tree_has_comparison_p (gimple_assign_rhs1 (g), bb)
+      && !ccmp_tree_has_comparison_p (gimple_assign_rhs2 (g), bb))
+    return NULL_RTX;
+
   last = get_last_insn ();
 
   rtx_insn *prep_seq = NULL, *gen_seq = NULL;
diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp_7.c b/gcc/testsuite/gcc.target/aarch64/ccmp_7.c
new file mode 100644
index 00000000000..29e269b854e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/ccmp_7.c
@@ -0,0 +1,46 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* PR middle-end/109832 */
+
+/* A conditional compare folds a comparison into the flags.  When the operands
+   are plain booleans there is no comparison to fold and the bitwise operation
+   is cheaper, so no conditional compare should be formed.  */
+
+_Bool
+bool_ior (_Bool x, _Bool y)
+{
+  return x || y;
+}
+
+_Bool
+bool_and (_Bool x, _Bool y)
+{
+  return x && y;
+}
+
+extern _Bool t (void);
+
+_Bool
+bool_call_ior (void)
+{
+  _Bool x = t ();
+  _Bool y = t ();
+  return x | y;
+}
+
+_Bool
+bool_ior_tree (_Bool a, _Bool b, _Bool c, _Bool d)
+{
+  return (a | b) | (c | d);
+}
+
+/* One explicit comparison is enough to keep each chain profitable.  */
+
+int
+bool_and_cmp_tree (_Bool a, _Bool b, _Bool c, int x, int y)
+{
+  return ((a & b) & c) & (x < y);
+}
+
+/* { dg-final { scan-assembler-times {\tccmp\t} 3 } } */
+/* { dg-final { scan-assembler-times {\torr\t} 5 } } */
-- 
2.50.1 (Apple Git-155)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.