On Tue, 18 Nov 2025, Dhruv Chawla wrote:

> On 18/11/25 18:14, Richard Biener wrote:
> > External email: Use caution opening links or attachments
> > 
> > 
> > On Tue, 18 Nov 2025, [email protected] wrote:
> > 
> >> From: Dhruv Chawla <[email protected]>
> >>
> >> The patch previously committed as r16-5161-gc4ca512358be7c would
> >> miscompile the cases where the LHS was unsigned and overflowed, as the
> >> comparison would then give a different result. For example:
> >>
> >> __attribute__ ((noipa)) bool
> >> lshift_lt(unsigned x, unsigned y)
> >> {
> >>    if (y <= 0)
> >>      __builtin_unreachable ();
> >>    return (y << x) < x;
> >> }
> >>
> >> int main()
> >> {
> >>    if (!lshift_lt(1, 0x80000000))
> >>      __builtin_abort();
> >> }
> >>
> >> Here 0x80000000 << 1 evaluates to 0 which is < 1 hence the comparison
> >> evaluates to true. However this currently gets optimized to false, and
> >> similar cases are there for the other operators as well. Therefore this
> >> is only valid to do in the cases where overflow is undefined.
> > 
> > Hmm, but left-shift overflow is not subject to undefined behavior on
> > overflow in GIMPLE, because it is not in C++.  So we have to drop
> > this optimization?
> 
> The problem is not necessarily due to well-definedness, it is due to the
> wrapping behaviour. This pattern ideally also needs to check if wrapping
> occurs or not and I added the UB check to try and avoid that.
> 
> If there is a better way to check if wrapping/overflow occurs then that
> would be a better solution. I had tried using ranger for this before but
> it didn't seem to work.

You could possibly use tree_nonzero_bits (@0) and verify all upper
N bits are not set for x << N.

Other than that, you'd have to drop the relational bits.
Richard.

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)

Reply via email to