The test is trying to shift by 129, but the underlying type is 128 bits. This causes low_bits to wrap around to -1 and things go bad really quick.
Attached is my proposed solution. Andrew, do you have a preference on how to fix this? gcc/ChangeLog: PR tree-optimization/97488 * range-op.cc (operator_lshift::op1_range): Handle large right shifts. gcc/testsuite/ChangeLog: * gcc.dg/pr97488.c: New test. --- gcc/range-op.cc | 6 ++++-- gcc/testsuite/gcc.dg/pr97488.c | 11 +++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr97488.c diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 30d2a4d3987..13a0ee37feb 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -1608,8 +1608,10 @@ operator_lshift::op1_range (irange &r, // This would be [0x42, 0xFC] aka [01000010, 11111100]. // Ideally we do this for each subrange, but just lump them all for now. - unsigned low_bits = TYPE_PRECISION (utype) - - TREE_INT_CST_LOW (shift_amount); + unsigned saturated_shift_amount = TREE_INT_CST_LOW (shift_amount); + if (saturated_shift_amount > TYPE_PRECISION (utype)) + saturated_shift_amount = TYPE_PRECISION (utype); + unsigned low_bits = TYPE_PRECISION (utype) - saturated_shift_amount; wide_int up_mask = wi::mask (low_bits, true, TYPE_PRECISION (utype)); wide_int new_ub = wi::bit_or (up_mask, r.upper_bound ()); wide_int new_lb = wi::set_bit (r.lower_bound (), low_bits); diff --git a/gcc/testsuite/gcc.dg/pr97488.c b/gcc/testsuite/gcc.dg/pr97488.c new file mode 100644 index 00000000000..96dc33cf258 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr97488.c @@ -0,0 +1,11 @@ +// { dg-do compile } +// { dg-options "-O1 -ftree-vrp" } + +__int128 +ef (__int128 ms) +{ + int dh = 129; + int *hj = &dh; + + return ms << *hj ? ms : 0; +} -- 2.25.4