https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66591
Bug ID: 66591 Summary: [SH] ICE: in get_reload_reg, at lra-constraints.c:633 with -mlra Product: gcc Version: 6.0 Status: UNCONFIRMED Keywords: ice-on-valid-code Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: kkojima at gcc dot gnu.org CC: olegendo at gcc dot gnu.org Target Milestone: --- Target: sh*-*-* When I tried to build trunk with cross SH trunk compiler, I've got tree-ssa-math-opts.c:1030:1: internal compiler error: in get_reload_reg, at lra-constraints.c:633 Here is a reduced test case static const unsigned char table[8] = { 0, 1, 1, 2, 2, 3, 3, 4, }; int foo (long long n) { if (n && n < 8) foo (table[n]); return 0; } The problem starts when LRA tries to reload the insn (insn 23 22 24 5 (set (reg:QI 181) (mem/u/j:QI (plus:SI (reg/f:SI 179) (subreg:SI (reg/v:DI 168 [ n ]) 0)) [0 table S1 A8])) rel.cc:7 271 {*movqi} (expr_list:REG_DEAD (reg/f:SI 179) (expr_list:REG_DEAD (reg/v:DI 168 [ n ]) (nil)))) .reload says Creating newreg=189 from oldreg=168, assigning class R0_REGS to address r189 Creating newreg=190 from oldreg=189, assigning class R0_REGS to address r190 Creating newreg=191 from oldreg=190, assigning class R0_REGS to address r191 ... Creating newreg=279 from oldreg=278, assigning class R0_REGS to address r279 which shows that something loops. It looks that LRA tries to find DImode R0_REGS hardware register for reg 168 and fails to do so because R1 is allocated already in the above test case unfortuantely. So LRA gives another DImode newreg for it and tries again. Thus it drops into the loop. This won't happen on other targets which have enough index registers and looks to be very rare even on SH in the actual codes. I think that pre-allocating R0 is enough for that issue ATM. It would be a yet another issue that is appropriate for R0-preallocating pass. Now I'm testing the patch below. diff --git a/config/sh/sh.c b/config/sh/sh.c index 8fc8197..af8727e 100644 --- a/config/sh/sh.c +++ b/config/sh/sh.c @@ -1780,7 +1780,6 @@ prepare_move_operands (rtx operands[], machine_mode mode) win on avarage for LRA. */ else if (sh_lra_p () && TARGET_SH1 && ! TARGET_SH2A - && (mode == QImode || mode == HImode) && ((REG_P (operands[0]) && MEM_P (operands[1])) || (REG_P (operands[1]) && MEM_P (operands[0])))) { @@ -1788,7 +1787,8 @@ prepare_move_operands (rtx operands[], machine_mode mode) rtx reg = operands[load_p ? 0 : 1]; rtx adr = XEXP (operands[load_p ? 1 : 0], 0); - if (REGNO (reg) >= FIRST_PSEUDO_REGISTER + if ((mode == QImode || mode == HImode) + && REGNO (reg) >= FIRST_PSEUDO_REGISTER && GET_CODE (adr) == PLUS && REG_P (XEXP (adr, 0)) && (REGNO (XEXP (adr, 0)) >= FIRST_PSEUDO_REGISTER) @@ -1800,6 +1800,17 @@ prepare_move_operands (rtx operands[], machine_mode mode) emit_move_insn (r0_rtx, operands[1]); operands[1] = r0_rtx; } + if (REGNO (reg) >= FIRST_PSEUDO_REGISTER + && GET_CODE (adr) == PLUS + && REG_P (XEXP (adr, 0)) + && (REGNO (XEXP (adr, 0)) >= FIRST_PSEUDO_REGISTER) + && SUBREG_P (XEXP (adr, 1)) + && REG_P (SUBREG_REG (XEXP (adr, 1)))) + { + rtx r0_rtx = gen_rtx_REG (GET_MODE (XEXP (adr, 1)), R0_REG); + emit_move_insn (r0_rtx, XEXP (adr, 1)); + XEXP (adr, 1) = r0_rtx; + } } }