https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126698
Drea Pinski <pinskia at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Last reconfirmed| |2026-08-06
Ever confirmed|0 |1
Status|UNCONFIRMED |NEW
--- Comment #1 from Drea Pinski <pinskia at gcc dot gnu.org> ---
The generic version is:
```
int f2 (unsigned x, unsigned t1)
{
unsigned t = (x & ((1u<<t1) - 1)) != 0;
return ((x >> t1) + t) == 0;
}
```
That is (x>>y + ((x&mask)!=0)) == 0
where mask is ((1u<<y) - 1) or rather the lower y bits.
The reason is when x is 0, then x&mask will be zero then x&mask will be 0 also.
And then x>>y will not overflow when adding 1 or 0. When y is 0 then it is just
`x == 0`. And (x>>y<<y)|((x&mask)!=0) is the same as x.
Note LLVM only handles the constant case. I don't see why we can't handle the
non-constant case.
Note it might be the case where LLVM actually turns (a+b) == 0 into a == 0 && b
== 0 and then optimizes that; I have not looked fully.
Because LLVM is able to optimize:
```
int f2 (unsigned x, unsigned t1)
{
t1 = 4;
unsigned t = (x & ((1u<<t1) - 1)) != 0;
return (x >> t1) == 0 && t == 0;
}
```
But LLVM is not able to optimize:
```
int f2 (unsigned x, unsigned t1)
{
t1 = 4;
return ((x >> t1)|(x & ((1u<<t1) - 1))) == 0;
}
```
So I am not sure how LLVM optimizes it fully; maybe it is just matching the !=
case.