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)
