https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97488
Aldy Hernandez <aldyh at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2020-10-19 Ever confirmed|0 |1 --- Comment #1 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- Confirmed. The shift amount in operator_lshift::op1_range is > than the precision of the type so the low_bits wrap around. Testing the following: 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);