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)
>

Reply via email to