Ping.
https://gcc.gnu.org/pipermail/gcc-patches/2026-August/727174.html
Thanks,
Kyrill

> On 11 Aug 2026, at 12:42, Kyrylo Tkachov <[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.  Every statement of a
> candidate has a leaf operand, so the candidate is a chain and the check
> walks it with a loop.
> 
> Bootstrapped and tested on aarch64-none-linux-gnu.
> Ok for trunk?
> Thanks,
> Kyrill
> 
> gcc/
> 
> PR middle-end/109832
> * ccmp.cc (ccmp_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.
> * gcc.target/aarch64/ccmp_9.c: Likewise.
> 
> Signed-off-by: Kyrylo Tkachov <[email protected]>
> ---
> gcc/ccmp.cc                               | 34 ++++++++++++++++++++
> gcc/testsuite/gcc.target/aarch64/ccmp_7.c | 38 +++++++++++++++++++++++
> gcc/testsuite/gcc.target/aarch64/ccmp_9.c | 14 +++++++++
> 3 files changed, 86 insertions(+)
> create mode 100644 gcc/testsuite/gcc.target/aarch64/ccmp_7.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/ccmp_9.c
> 
> diff --git a/gcc/ccmp.cc b/gcc/ccmp.cc
> index 0564ccf34bf..d35e05ec375 100644
> --- a/gcc/ccmp.cc
> +++ b/gcc/ccmp.cc
> @@ -90,6 +90,35 @@ ccmp_tree_comparison_p (tree t, basic_block bb)
>    If all checks OK in expand_ccmp_expr, it emits insns in prep_seq, then
>    insns in gen_seq.  */
> 
> +/* Return true if candidate G in BB has a comparison to fold into the
> +   condition flags.  Every statement of a candidate has a leaf operand, so
> +   the candidate is a chain and this walks it down to its innermost
> +   statement.  A leaf that has a defining statement is a comparison, the
> +   other leaves are booleans that expand to a comparison against zero.  */
> +
> +static bool
> +ccmp_has_comparison_p (gimple *g, basic_block bb)
> +{
> +  do
> +    {
> +      tree op0 = gimple_assign_rhs1 (g);
> +      tree op1 = gimple_assign_rhs2 (g);
> +      bool leaf0 = ccmp_tree_comparison_p (op0, bb);
> +      bool leaf1 = ccmp_tree_comparison_p (op1, bb);
> +
> +      gcc_checking_assert (leaf0 || leaf1);
> +
> +      if ((leaf0 && get_gimple_for_ssa_name (op0))
> +  || (leaf1 && get_gimple_for_ssa_name (op1)))
> + return true;
> +
> +      g = get_gimple_for_ssa_name (leaf0 ? op1 : op0);
> +    }
> +  while (g);
> +
> +  return false;
> +}
> +
> /* Check whether G is a potential conditional compare candidate; OUTER is 
> true if
>    G is the outer most AND/IOR.  */
> static bool
> @@ -294,6 +323,11 @@ expand_ccmp_expr (gimple *g, machine_mode mode)
>   if (!ccmp_candidate_p (g, true))
>     return NULL_RTX;
> 
> +  /* A conditional compare folds a comparison into the flags.  Without a
> +     comparison to fold the bitwise operation is cheaper.  */
> +  if (!ccmp_has_comparison_p (g, gimple_bb (g)))
> +    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..d9c75eb6b0b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp_7.c
> @@ -0,0 +1,38 @@
> +/* { 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);
> +}
> +
> +/* { dg-final { scan-assembler-not {\tccmp\t} } } */
> +/* { dg-final { scan-assembler-times {\torr\tw[0-9]+, w[0-9]+, w[0-9]+} 5 } 
> } */
> diff --git a/gcc/testsuite/gcc.target/aarch64/ccmp_9.c 
> b/gcc/testsuite/gcc.target/aarch64/ccmp_9.c
> new file mode 100644
> index 00000000000..4f95ddf53c1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/ccmp_9.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +/* PR middle-end/109832 */
> +
> +/* One explicit comparison is enough for a chain to be worth a conditional
> +   compare, so the boolean operands become a compare against zero.  */
> +
> +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} 1 } } */
> -- 
> 2.50.1 (Apple Git-155)
> 

Reply via email to