https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93376
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rsandifo at gcc dot gnu.org --- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> --- The problem seems to be during try_combine: (gdb) p debug_rtx (i3) (insn 18 17 19 2 (parallel [ (set (reg:CCO 17 flags) (eq:CCO (plus:OI (sign_extend:OI (reg:TI 96)) (const_int 1 [0x1])) (sign_extend:OI (plus:TI (reg:TI 96) (const_int 1 [0x1]))))) (set (reg:TI 98) (plus:TI (reg:TI 96) (const_int 1 [0x1]))) ]) "pr93376.c":8:10 223 {*addvti4_doubleword_1} (expr_list:REG_UNUSED (reg:TI 98) (expr_list:REG_DEAD (reg:TI 96) (nil)))) (gdb) p debug_rtx (i2) (insn 17 37 18 2 (set (reg:TI 96) (const_wide_int 0x7fffffffffffffffffffffffffffffff)) "pr93376.c":8:10 65 {*movti_internal} (nil)) The eq in there gets simplified into: (eq:CCO (const_wide_int 0x080000000000000000000000000000000) (const_wide_int 0x80000000000000000000000000000000)) (correct), where the first CONST_WIDE_INT has 3 elts (as it is the TImode MS bit zero extended into OImode) and the second one has 2 elts (the same sign-extended into OImode). The problem is that i386.md has /* Keep the OI and XI modes from confusing the compiler into thinking that these modes could actually be used for computation. They are only holders for vectors during data movement. */ #define MAX_BITSIZE_MODE_ANY_INT (128) which means WIDE_INT_MAX_ELTS is 3, which is big enough to handle all that the patterns need, they only need one hwi above the TImode bits to detect overflow in either way (maybe even just 1-2 bits). I'm afraid we don't want to bump MAX_BITSIZE_MODE_ANY_INT, because it would have consequences anywhere. Anyway, what happens when simplify-rtx.c calls: 4443 case MINUS: 4444 result = wi::sub (pop0, pop1); 4445 break; (gdb) p pop0 $44 = {<std::__pair_base<rtx_def*, machine_mode>> = {<No data fields>}, (const_wide_int 0x080000000000000000000000000000000)first = , second = E_OImode} (gdb) p pop1 $45 = {<std::__pair_base<rtx_def*, machine_mode>> = {<No data fields>}, (const_wide_int 0x80000000000000000000000000000000)first = , second = E_OImode} again, len 3 and len 2. That results in wi::sub creating result of: $47 = {<wide_int_storage> = {val = {8589917872, 140737127633408, 140737488338464}, len = 13162290, precision = 256}, static is_sign_extended = true} where the val array has 3 elts, but then: 2539 result.set_len (sub_large (val, xi.val, xi.len, 2540 yi.val, yi.len, precision, 2541 UNSIGNED, 0)); and that one unnecessarily uses yet another HWI, overwriting precision in the wide_int_storage. The following fixes the ICE, Richard S., would this be acceptable to you? Only the second hunk is strictly necessary. --- gcc/wide-int.cc.jj 2020-01-12 11:54:38.535381394 +0100 +++ gcc/wide-int.cc 2020-01-22 12:05:06.739486117 +0100 @@ -1155,8 +1155,14 @@ wi::add_large (HOST_WIDE_INT *val, const if (len * HOST_BITS_PER_WIDE_INT < prec) { - val[len] = mask0 + mask1 + carry; - len++; + HOST_WIDE_INT val_top = mask0 + mask1 + carry; + /* Don't extend len unnecessarily when canonize would shrink it + again immediately. */ + if (SIGN_MASK (val[len - 1]) != val_top) + { + val[len] = val_top; + len++; + } if (overflow) *overflow = (sgn == UNSIGNED && carry) ? wi::OVF_OVERFLOW : wi::OVF_NONE; @@ -1566,8 +1572,14 @@ wi::sub_large (HOST_WIDE_INT *val, const if (len * HOST_BITS_PER_WIDE_INT < prec) { - val[len] = mask0 - mask1 - borrow; - len++; + HOST_WIDE_INT val_top = mask0 - mask1 - borrow; + /* Don't extend len unnecessarily when canonize would shrink it + again immediately. */ + if (SIGN_MASK (val[len - 1]) != val_top) + { + val[len] = val_top; + len++; + } if (overflow) *overflow = (sgn == UNSIGNED && borrow) ? OVF_UNDERFLOW : OVF_NONE; }