On Tue, 13 Oct 2026, [email protected] wrote:

> From: Kyrylo Tkachov <[email protected]>
> 
> For 0 < C < prec the fold
> 
>   .CTZ (x, V) >= C -> (x & ((1 << C) - 1)) == 0
>   .CTZ (x, V) < C -> (x & ((1 << C) - 1)) != 0
> 
> applies when V < 0 or V >= prec.  For x = 0 the bit test is true, so the
> fold is correct only if V >= C.  For
> 
>   _1 = .CTZ (x_4(D), -1);
>   _2 = _1 >= 3;
> 
> and x = 0, _2 is 0, but the fold gives
> 
>   _5 = x_4(D) & 7;
>   _2 = _5 == 0;
> 
> which is 1.  gcn, and rs6000 without TARGET_CTZ and TARGET_POPCNTD,
> define -1 as the value at zero, so __builtin_ctzg (x, -1) >= 3 is
> miscompiled there.  The condition comes from r12-151 (PR95527).
> 
> Fold only if V >= C.
> 
> Bootstrapped and tested on aarch64-none-linux-gnu and x86_64-linux.

OK.  Can you make sure to fix affected branches as well?

Thanks,
Richard.

> gcc/ChangeLog:
> 
>       * match.pd (.CTZ (x, V) >= C -> (x & ((1 << C) - 1)) == 0):
>       Require that the value at zero is at least C.
> 
> gcc/testsuite/ChangeLog:
> 
>       * gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c: New test.
> 
> Signed-off-by: Kyrylo Tkachov <[email protected]>
> ---
>  gcc/match.pd                                  |  2 +-
>  .../gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c | 69 +++++++++++++++++++
>  2 files changed, 70 insertions(+), 1 deletion(-)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c
> 
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 68b910e337b..ebbe24c0aea 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -11421,7 +11421,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>        (if (val >= prec)
>         (if (ok && zero_val < val)
>       { constant_boolean_node (cmp != EQ_EXPR, type); })
> -       (if (ok && (zero_val < 0 || zero_val >= prec))
> +       (if (ok && zero_val >= val)
>       (cmp (bit_and @0 { wide_int_to_tree (type0,
>                                            wi::mask (val, false, prec)); })
>            { build_zero_cst (type0); })))))))
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c
> new file mode 100644
> index 00000000000..5a159ec2d08
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/ctz-cmp-value-at-zero-1.c
> @@ -0,0 +1,69 @@
> +/* .CTZ (X, V) >= C becomes (X & ((1 << C) - 1)) == 0 only if V >= C,
> +   because the bit test is true for X = 0.  */
> +/* { dg-do compile } */
> +/* { dg-require-effective-target int32 } */
> +/* { dg-require-effective-target ctz_ifn } */
> +/* { dg-options "-O2 -fgimple -fdump-tree-optimized" } */
> +
> +/* .CTZ (0, -1) is -1, which is smaller than 3.  */
> +
> +int __GIMPLE (ssa)
> +gem1 (unsigned int x)
> +{
> +  int _1;
> +  _Bool _2;
> +  int _3;
> +
> +  __BB(2):
> +  _1 = .CTZ (x_4(D), -1);
> +  _2 = _1 >= 3;
> +  _3 = (int) _2;
> +  return _3;
> +}
> +
> +int __GIMPLE (ssa)
> +ltm1 (unsigned int x)
> +{
> +  int _1;
> +  _Bool _2;
> +  int _3;
> +
> +  __BB(2):
> +  _1 = .CTZ (x_4(D), -1);
> +  _2 = _1 < 3;
> +  _3 = (int) _2;
> +  return _3;
> +}
> +
> +/* .CTZ (0, 32) is 32, which is not smaller than 3.  */
> +
> +int __GIMPLE (ssa)
> +ge32 (unsigned int x)
> +{
> +  int _1;
> +  _Bool _2;
> +  int _3;
> +
> +  __BB(2):
> +  _1 = .CTZ (x_4(D), 32);
> +  _2 = _1 >= 3;
> +  _3 = (int) _2;
> +  return _3;
> +}
> +
> +int __GIMPLE (ssa)
> +lt32 (unsigned int x)
> +{
> +  int _1;
> +  _Bool _2;
> +  int _3;
> +
> +  __BB(2):
> +  _1 = .CTZ (x_4(D), 32);
> +  _2 = _1 < 3;
> +  _3 = (int) _2;
> +  return _3;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "\\.CTZ" 2 "optimized" } } */
> +/* { dg-final { scan-tree-dump-times " & 7;" 2 "optimized" } } */
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to