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)
