https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112509
--- Comment #2 from Andrew Macleod <amacleod at redhat dot com> --- the original switch is an unsigned value with precision of 3 bits, so 0..7 just fits. It gets translated to an int index during gimplification, but the case labels are still precision 3 values. find_case_label_ranges in tree-vrp.cc does the following: tree label = gimple_switch_label (switch_stmt, i); tree case_high = CASE_HIGH (label) ? CASE_HIGH (label) : CASE_LOW (label); wide_int wlow = wi::to_wide (CASE_LOW (label)); wide_int whigh = wi::to_wide (case_high); int_range_max label_range (type, wide_int::from (wlow, prec, sign), wide_int::from (whigh, prec, sign)); CASE_HIGH is indeed 6, but when we to the to_wide call, it is sign extended to produce: (gdb) p whigh.dump () [0xfffffffffffffffe], precision = 3 but then when we do wide_int::from() in the signed int precision 32 of the new switch type, we get -2 for the high value. Whats suppose to happen here? seems odd to me that the case labels are a different precision than the switch itself.. but then we would also lose the fact that there is only 3 bits of precision in the switch. Should the low and high values be cast from the original case precision/type to the new perhaps? something like this seems to work: tree find_case_label_range (gswitch *switch_stmt, const irange *range_of_op) @@ -900,9 +901,9 @@ find_case_label_range (gswitch *switch_stmt, const irange *range_of_op) = CASE_HIGH (label) ? CASE_HIGH (label) : CASE_LOW (label); wide_int wlow = wi::to_wide (CASE_LOW (label)); wide_int whigh = wi::to_wide (case_high); - int_range_max label_range (type, - wide_int::from (wlow, prec, sign), - wide_int::from (whigh, prec, sign)); + int_range_max label_range (TREE_TYPE (case_high), wlow, whigh); + range_cast (label_range, type); + label_range.dump(stderr);