https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69771
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords|wrong-code | --- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- Hmm, I think that's ok. ~b is always true, it is ~(int)b != 0 but b is unsigned short and thus zero-extended which means the upper bits are always 1. Thus ~(a || ~b) is 0xfffffffe. Now since some C FE change the shift count is interpreted as unsigned char and thus we end up with d >> 0xfe which is indeed zero. On the GCC 5 branch we have an int shift count and thus end up with -2 and a different result (target dependent). So it's really the ICE we're after, no wrong-code. And it's a bogus integer constant (not canonicalized) that triggers the issue. (insn 7 6 8 2 (set (reg:QI 90) (const_int 254 [0xfe])) t.i:5 -1 (nil)) a QImode 0xfe should be sign-extended. It's expand_binop_directly doing mode1 = GET_MODE (xop1) != VOIDmode ? GET_MODE (xop1) : mode; if (xmode1 != VOIDmode && xmode1 != mode1) { xop1 = convert_modes (xmode1, mode1, xop1, unsignedp); mode1 = xmode1; } with VOIDmode xop1, expanded from a int typed constant and thus canonicalized to SImode. We fail to canonicalize the constant here if xmode1 (QImode) and mode (QImode) match. Index: gcc/optabs.c =================================================================== --- gcc/optabs.c (revision 233369) +++ gcc/optabs.c (working copy) @@ -1020,8 +1020,8 @@ expand_binop_directly (machine_mode mode mode0 = xmode0; } - mode1 = GET_MODE (xop1) != VOIDmode ? GET_MODE (xop1) : mode; - if (xmode1 != VOIDmode && xmode1 != mode1) + mode1 = GET_MODE (xop1); + if (xmode1 != mode1) { xop1 = convert_modes (xmode1, mode1, xop1, unsignedp); mode1 = xmode1; fixes this by always converting VOIDmode inputs. The comment even says so: /* In case the insn wants input operands in modes different from those of the actual operands, convert the operands. It would seem that we don't need to convert CONST_INTs, but we do, so that they're properly zero-extended, sign-extended or truncated for their mode. */ but for some reason the code doesn't agree with it.