https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95396
--- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Richard Biener from comment #6) > One odd thing is that for unsigned char _3 we get via > > wide_int var_min, var_max; > value_range_kind vr_type = get_range_info (tmp_var, &var_min, > &var_max); > > [241, 255] > > the add of 15 then overflows for both min and max and thus we happily accept > the result but compute the difference signed (in widest_int): > > /* Calculate (ssizetype) OP0 - (ssizetype) TMP_VAR. */ > widest_int diff = (widest_int::from (op0_min, sgn) > - widest_int::from (var_min, sgn)); > var0 = tmp_var; > *off = wide_int_to_tree (ssizetype, diff); > > which then results in 0-241 == -241. > > To me it looks like we should instead do > > /* Calculate (ssizetype) (OP0 - TMP_VAR). */ > widest_int diff = widest_int::from (op0_min - var_min, sgn); > > which fixes this particular testcase. Or alternatively widest_int diff = wi::ext (widest_int::from (op0_min, sgn) - widest_int::from (var_min, sgn), TYPE_PRECISION (type), TYPE_SIGN (type)); which maybe more highlights the underlying issue (failing zero-extension for the sign-changing conversion)? I don't expect any fallout of either patch possibly due to bad test coverage so extra thoughts welcome.