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"). 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]) So this is where I've been banging my head against the sources... where is the magic that tells gcc to try to copy everything into registers to meet the constraints? Note: expand is ok, the initial add insn is: (insn 9 3 10 2 (set (reg:HI 48 [ D.1375 ]) (plus:HI (reg/v:HI 45 [ x ]) (mem/c:HI (symbol_ref:SI ("b") <var_decl 0x7f1123d89428 b>) [2 b+0 S2 A16 AS2]))) dj.c:43 -1 (nil)) and just before reload: (insn 10 9 0 2 (set (mem/c:HI (symbol_ref:SI ("a") <var_decl 0x7f1123d89390 a>) [2 a+0 S2 A16 AS2]) (plus:HI (mem/c:HI (reg/f:HI 33 ap) [2 x+0 S2 A16]) (mem/c:HI (symbol_ref:SI ("b") <var_decl 0x7f1123d89428 b>) [2 b+0 S2 A16 AS2]))) dj.c:43 13 {*addhi3_virt} (nil))