http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59559
Bug ID: 59559 Summary: ICE: invalid RTX sharing in expmed.c:expand_divmod Product: gcc Version: 4.8.3 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: gjl at gcc dot gnu.org In expmed.c:expand_divmod() we have the following code: t1 = expmed_mult_highpart (compute_mode, op0, gen_int_mode (ml, compute_mode), NULL_RTX, 1, max_cost - extra_cost); if (t1 == 0) goto fail1; t2 = force_operand (gen_rtx_MINUS (compute_mode, op0, t1), NULL_RTX); t3 = expand_shift (RSHIFT_EXPR, compute_mode, t2, 1, NULL_RTX, 1); t4 = force_operand (gen_rtx_PLUS (compute_mode, t1, t3), NULL_RTX); This code produces invalid RTX sharing for t1 if some conditions are met: - The code is used after tree->RTL lowering which can happen in some loop optimizations. A possible call chain is from loop_doloop.c:doloop_modify() and if the force_operand there operates on a UDIV or DIV expression and finally ends up with the expmed.c code from above. - The value for t1 is a SUBREG like (subreg:SI (reg:DI xxx) 4) This depends on the backend and if and how it implements (widening) multiplication and mul_highpart insns. - The ICE will depend on the cost model of the target. - The ICE will only pop up if RTL checking is enabled. I could not reproduce this ICE with a standard GCC target, I just see it for a private port. However, this might also be a latent problem for official GCC targets. The problem is that the loop optimization above runs after RTL unsharing so that the sharing of the SUBREG is not resolved. A possible fix is obviously to t1 = copy_rtx (t1) after the first use of t1 and befor its second use. FYI, the code for which I see the ICE is gcc.c-torture/execute/loop-3b.c from GCC's test suite -- but as already said I found no official target that breaks there. There is also a simpler example like the code below, but fpr x86 and rs6000 it works fine :-( int n; void f (int val) { while (n > 0) { val++; n -=45; } }