On 09/01/2015 01:44 AM, DJ Delorie wrote:
Given this test case for rl78-elf:
extern __far int a, b;
void ffr (int x)
{
a = b + x;
}
I'm trying to use this patch:
Index: gcc/config/rl78/rl78-virt.md
===================================================================
--- gcc/config/rl78/rl78-virt.md (revision 227360)
+++ gcc/config/rl78/rl78-virt.md (working copy)
@@ -92,15 +92,15 @@
]
"rl78_virt_insns_ok ()"
"v.inc\t%0, %1, %2"
)
(define_insn "*add<mode>3_virt"
- [(set (match_operand:QHI 0 "rl78_nonfar_nonimm_operand" "=vY,S")
- (plus:QHI (match_operand:QHI 1 "rl78_nonfar_operand" "viY,0")
- (match_operand:QHI 2 "rl78_general_operand" "vim,i")))
+ [(set (match_operand:QHI 0 "rl78_nonimmediate_operand" "=vY,S,Wfr")
+ (plus:QHI (match_operand:QHI 1 "rl78_general_operand" "viY,0,0")
+ (match_operand:QHI 2 "rl78_general_operand" "vim,i,vi")))
]
"rl78_virt_insns_ok ()"
"v.add\t%0, %1, %2"
)
(define_insn "*sub<mode>3_virt"
To allow the rl78 port to generate the "Wfr/0/r" case (alternative 3).
(Wfr = far MEM, v = virtual regs).
I expected gcc to see that the operation doesn't meet the constraints,
and move operands into registers to make it work (alternative 1,
"v/v/v").
That'd be my expectation as well. Note that addXX patterns may be
special. I can recall a fair amount of pain with them on oddball ports.
Instead, it just complains and dies.
dj.c:42:1: error: insn does not satisfy its constraints:
}
^
(insn 10 15 13 2 (set (mem/c:HI (reg:SI 8 r8) [1 a+0 S2 A16 AS2])
(plus:HI (mem/c:HI (plus:HI (reg/f:HI 32 sp)
(const_int 4 [0x4])) [1 x+0 S2 A16])
(mem/c:HI (symbol_ref:SI ("b") <var_decl 0x7f676f97d3f0 b>) [1 b+0
S2 A16 AS2]))) dj.c:41 13 {*addhi3_virt}
(nil))
dj.c:42:1: internal compiler error: in extract_constrain_insn, at recog.c:2200
Reloads for insn # 10
Reload 0: reload_in (SI) = (symbol_ref:SI ("a") <var_decl 0x7fb91247e390 a>)
V_REGS, RELOAD_FOR_INPUT (opnum = 0), inc by 2
reload_in_reg: (symbol_ref:SI ("a") <var_decl 0x7fb91247e390 a>)
reload_reg_rtx: (reg:SI 8 r8)
Reload 1: reload_in (HI) = (mem/c:HI (plus:HI (reg/f:HI 32 sp)
(const_int 4 [0x4]))
[2 x+0 S2 A16])
reload_out (HI) = (mem/c:HI (plus:HI (reg/f:HI 32 sp)
(const_int 4 [0x4]))
[2 x+0 S2 A16])
V_REGS, RELOAD_OTHER (opnum = 1), optional
reload_in_reg: (mem/c:HI (plus:HI (reg/f:HI 32 sp)
(const_int 4 [0x4]))
[2 x+0 S2 A16])
reload_out_reg: (mem/c:HI (plus:HI (reg/f:HI 32 sp)
(const_int 4 [0x4]))
[2 x+0 S2 A16])
Reload 2: reload_in (HI) = (mem/c:HI (symbol_ref:SI ("b") <var_decl
0x7fb91247e428 b>) [2 b+0 S2 A16 AS2])
V_REGS, RELOAD_FOR_INPUT (opnum = 2), optional
reload_in_reg: (mem/c:HI (symbol_ref:SI ("b") <var_decl 0x7fb91247e428
b>) [2 b+0 S2 A16 AS2])
Note that reload 1 and reload 2 do not have a reload_reg_rtx. My
memories of reload are fading fast (thank goodness), but I believe
that's an indication that it's not reloading into a hard register.
So I'd start with looking at find_reloads/push_reload and figure out why
it's not getting a suitable register. It might be good to know what
alternative is being targeted by reload. ie, you'll be looking at
goal_alternative* in find_reloads.
Again, my memories are getting stale here, so double-check the meaning
of reload_reg_rtx ;-)
jeff