This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/66591] New: [SH] ICE: in get_reload_reg, at lra-constraints.c:633 with -mlra
- From: "kkojima at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Fri, 19 Jun 2015 00:13:40 +0000
- Subject: [Bug target/66591] New: [SH] ICE: in get_reload_reg, at lra-constraints.c:633 with -mlra
- Auto-submitted: auto-generated
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;
+ }
}
}