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

Andrea Pinski <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <CALvbMcD6qwjAaKyjHcz5PjfWF4-xG=k+VByvmTnxrzuHxqLV+Q@mail.gmail.com>
On Mon, Aug 10, 2026 at 6:23 AM <[email protected]> wrote:
>
> 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));

Is there a way to do this non recursive (and not with a work list)?
I think it might be a good idea to move ccmp away from expand into say isel.
We already don't really want to depend on TER and your above code does
not even use ter.

> +}
> +
>  /* 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.