Re: Problem with reloading in a new backend...
Le lundi 14 avril 2008 à 18:27 -0700, Jim Wilson a écrit : On Tue, 2008-04-15 at 00:06 +0200, Stelian Pop wrote: - I had to add a PLUS case in PREFERRED_RELOAD_CLASS() or else reload kept generating incorrect insn (putting constants into EVEN_REGS for example). I'm not sure this is correct or if it hides something else... It does sound odd, but I can't really say it is wrong, as you have an odd set of requirements here. At least it is working which is good. Ok, thanks again. Stelian. -- Stelian Pop [EMAIL PROTECTED]
Re: Problem with reloading in a new backend...
Le vendredi 11 avril 2008 à 11:14 -0700, Jim Wilson a écrit : Stelian Pop wrote: #define PREFERRED_RELOAD_CLASS(X, CLASS)\ ((CONSTANT_P(X)) ? EIGHT_REGS : \ (MEM_P(X)) ? EVEN_REGS : CLASS) #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \ ((CONSTANT_P(X)) ? EIGHT_REGS : \ (MEM_P(X)) ? EVEN_REGS : CLASS) I think most of your trouble is here. Suppose we are trying to reload a constant into an even-reg. We call PREFERRED_RELOAD_CLASS, which says to use eight_regs instead, and you get a fatal_insn error because you didn't get the even-reg that the instruction needed. [...] I've tried the suggestion above and it did indeed help. However, I had a few additional issues: - the stack pointer and the frame pointer MUST be placed into an even-reg, or else reload will generate (mem (plus (reg) (const))) insn (when eliminating the pointers). - I had to add a PLUS case in PREFERRED_RELOAD_CLASS() or else reload kept generating incorrect insn (putting constants into EVEN_REGS for example). I'm not sure this is correct or if it hides something else... #define STACK_POINTER_REGNUM 30 #define FRAME_POINTER_REGNUM 28 #define PREFERRED_RELOAD_CLASS(X, CLASS) ardac_preferred_reload_class(X, CLASS) #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) ardac_preferred_reload_class(X, CLASS) enum reg_class ardac_preferred_reload_class(rtx x, enum reg_class class) { if (CONSTANT_P(x)) { switch (class) { case NO_REGS: case STACK_REGS: return NO_REGS; case EVEN_REGS: case EIGHTEVEN_REGS: return EIGHTEVEN_REGS; case EIGHT_REGS: case GENERAL_REGS: return EIGHT_REGS; default: gcc_unreachable (); } } else if (MEM_P(x)) { switch (class) { case NO_REGS: case STACK_REGS: return NO_REGS; case EIGHT_REGS: case EIGHTEVEN_REGS: return EIGHTEVEN_REGS; case EVEN_REGS: case GENERAL_REGS: return EVEN_REGS; default: gcc_unreachable (); } } else { if (GET_CODE (x) == PLUS GET_CODE (XEXP (x, 0)) == REG GET_CODE (XEXP (x, 1)) == CONST_INT) { return EIGHTEVEN_REGS; } return class; } } Now it compiler 100+ files from libgcc without error so I guess the register assignment problem is solved. It now fails later: /home/tiniou/LTD/LTD/aRDAC/wip/src/gcc-4.3.0/libgcc/../gcc/unwind-dw2-fde.c: In function ‘frame_heapsort’: /home/tiniou/LTD/LTD/aRDAC/wip/src/gcc-4.3.0/libgcc/../gcc/unwind-dw2-fde.c:521: internal compiler error: in expand_call, at calls.c:3149 I haven't investigated why yet, but this is probably not related to the above. Thanks, -- Stelian Pop [EMAIL PROTECTED]
Re: Problem with reloading in a new backend...
On Tue, 2008-04-15 at 00:06 +0200, Stelian Pop wrote: - I had to add a PLUS case in PREFERRED_RELOAD_CLASS() or else reload kept generating incorrect insn (putting constants into EVEN_REGS for example). I'm not sure this is correct or if it hides something else... It does sound odd, but I can't really say it is wrong, as you have an odd set of requirements here. At least it is working which is good. Jim
Re: Problem with reloading in a new backend...
Stelian Pop wrote: #define PREFERRED_RELOAD_CLASS(X, CLASS)\ ((CONSTANT_P(X)) ? EIGHT_REGS : \ (MEM_P(X)) ? EVEN_REGS : CLASS) #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \ ((CONSTANT_P(X)) ? EIGHT_REGS : \ (MEM_P(X)) ? EVEN_REGS : CLASS) I think most of your trouble is here. Suppose we are trying to reload a constant into an even-reg. We call PREFERRED_RELOAD_CLASS, which says to use eight_regs instead, and you get a fatal_insn error because you didn't get the even-reg that the instruction needed. PREFERRED_RELOAD_CLASS must always return a class that is a strict subset of the class that was passed in. So define another register class which is the intersection of eight regs and even regs, and when we call PREFERRED_RELOAD_CLASS with a constant and even regs, then return the eight/even intersection class. Likewise in all of the other cases you are trying to handle. Fix this problem, and you probably don't need most of the other changes you have made recently. Jim
Re: Problem with reloading in a new backend...
Le vendredi 11 avril 2008 à 11:14 -0700, Jim Wilson a écrit : Stelian Pop wrote: #define PREFERRED_RELOAD_CLASS(X, CLASS)\ ((CONSTANT_P(X)) ? EIGHT_REGS : \ (MEM_P(X)) ? EVEN_REGS : CLASS) #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \ ((CONSTANT_P(X)) ? EIGHT_REGS : \ (MEM_P(X)) ? EVEN_REGS : CLASS) I think most of your trouble is here. Suppose we are trying to reload a constant into an even-reg. We call PREFERRED_RELOAD_CLASS, which says to use eight_regs instead, and you get a fatal_insn error because you didn't get the even-reg that the instruction needed. PREFERRED_RELOAD_CLASS must always return a class that is a strict subset of the class that was passed in. So define another register class which is the intersection of eight regs and even regs, and when we call PREFERRED_RELOAD_CLASS with a constant and even regs, then return the eight/even intersection class. Ah thanks, this does indeed seem to solve a lot of problems I had ! Likewise in all of the other cases you are trying to handle. Fix this problem, and you probably don't need most of the other changes you have made recently. I will still have the problems with the fact that my indirect addressing doesn't allow displacements, no ? (so I would need to implement LEGITIMIZE_RELOAD_ADDRESS, in which I'll need a special reserved register to compute the full address by adding the base and the displacement). Or do you imply that I won't need this anymore ? Thanks, -- Stelian Pop [EMAIL PROTECTED]
Re: Problem with reloading in a new backend...
On Sat, 2008-04-12 at 00:06 +0200, Stelian Pop wrote: I will still have the problems with the fact that my indirect addressing doesn't allow displacements, no ? (so I would need to implement LEGITIMIZE_RELOAD_ADDRESS, in which I'll need a special reserved register to compute the full address by adding the base and the displacement). Or do you imply that I won't need this anymore ? I didn't see an obvious explanation for your troubles here. There are other targets like IA-64 that do not have base+offset addressing modes. It should just work. LEGITIMIZE_RELOAD_ADDRESS is a hack. It should never be necessary for correct code generation, in theory, though I think there are some rare corner cases where it may be required for correct results. Long term this is something that should be fixed. Meanwhile, I can point out that the IA-64 port does not define LEGITIMIZE_RELOAD_ADDRESS, and does not have base+offset addressing modes, and it works. IA-64 does have auto-increment addressing modes, but those shouldn't matter here. Reload won't generate such addressing modes for a stack slot reference. Jim
Re: Problem with reloading in a new backend...
Stelian Pop wrote: I will still have the problems with the fact that my indirect addressing doesn't allow displacements, no ? (so I would need to implement LEGITIMIZE_RELOAD_ADDRESS, in which I'll need a special reserved register to compute the full address by adding the base and the displacement). Or do you imply that I won't need this anymore ? In your original message, the right thing happens. The stack slot address gets reloaded. (insn 1117 16 1118 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10) (const_int 24 [0x18])) 1 {*movqi_imm} (nil)) (insn 1118 1117 1119 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10) (plus:QI (reg:QI 10 r10) (reg/f:QI 30 r30))) 13 {addqi3} (expr_list:REG_EQUIV (plus:QI (reg/f:QI 30 r30) (const_int 24 [0x18])) (nil))) (insn 1119 1118 21 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (mem/c:QI (reg:QI 10 r10) [31 S1 A16]) (reg:QI 14 r14)) 8 {*movqi_tomem} (nil)) The only problem here is that the register choice is wrong, and I already explained why it is wrong. It is only after you started making some changes that this apparently broke. It isn't clear why. I can only suggest that you try to debug it. Put a breakpoint in find_reloads() conditional on the instruction number. Then step through to see what happens. It should call finds_reloads_address or find_reloads_toplev at some point, which will see that we don't have a strictly valid address, and then reload it. Jim
Re: Problem with reloading in a new backend...
Le mercredi 09 avril 2008 à 18:21 -0400, DJ Delorie a écrit : Maybe I should reserve a special register for this usage (say r0). That might be the only way, yes. Ok, I reserved r0 (BP_REGNUM) for such reloads, and I'm generating new instructions in LEGITIMIZE_RELOAD_ADDRESS to calculate the memory address: if (GET_CODE (*x) == PLUS GET_CODE (XEXP (*x, 0)) == REG GET_CODE (XEXP (*x, 1)) == CONST_INT) { rtx reginsn, setinsn, plusinsn; reginsn = gen_rtx_REG(Pmode, BP_REGNUM); setinsn = gen_rtx_SET(Pmode, reginsn, XEXP (*x, 1)); plusinsn = gen_rtx_SET(Pmode, reginsn, gen_rtx_PLUS(Pmode, reginsn, XEXP (*x, 0))); emit_insn_before(setinsn, insn); emit_insn_before(plusinsn, insn); *x = reginsn; return 1; } Does this sound ok ? Note that I needed to use emit_insn_before() in order to insert the instructions, and emit_insn_before() needs the current 'insn', which is not passed by LEGITIMIZE_RELOAD_ADDRESS(), so I needed to modify the macro. Is there something I miss here ? Note that reload also assumes that such adds don't change the flags (i.e. a compare/jump pair must not have a flag-modifying add between them). I think this won't happen because I emit the compare/conditional branch insn at the same time, in beq/bne/bgt... etc define_insn() (like many other targets). Thanks. -- Stelian Pop [EMAIL PROTECTED]
Re: Problem with reloading in a new backend...
Le jeudi 10 avril 2008 à 15:48 +0200, Stelian Pop a écrit : Le mercredi 09 avril 2008 à 18:21 -0400, DJ Delorie a écrit : Maybe I should reserve a special register for this usage (say r0). That might be the only way, yes. Ok, I reserved r0 (BP_REGNUM) for such reloads, and I'm generating new instructions in LEGITIMIZE_RELOAD_ADDRESS to calculate the memory address: [...] Now it seems that the register moves are correctly dealt with, but I'm still having the same problem on calls: just like indirect addressing, indirect calls are allowed only on even registers. My patterns look like: (define_insn *icall_value [(set (match_operand 0 register_operand =r) (call (mem:QI (match_operand:QI 1 register_operand z)) (match_operand:QI 2 )))] icall (%1) [(set_attr cc none)] ) (define_expand call_value [(set (match_operand 0 register_operand =r) (call (match_operand:QI 1 memory_operand m) (match_operand:QI 2 general_operand )))] { if (GET_CODE (XEXP(operands[1], 0)) != REG) XEXP(operands[1], 0) = force_reg (QImode, XEXP (operands[1], 0)); } ) This gives: (insn 27 26 29 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:564 (set (reg/f:QI 114) (symbol_ref:QI (__lshrqi3) [flags 0x41])) 1 {*movqi} (expr_list:REG_EQUIV (symbol_ref:QI (__lshrqi3) [flags 0x41]) (nil))) ... (call_insn/u 30 29 31 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:564 (set (reg:QI 4 r4) (call (mem:QI (reg/f:QI 114) [0 S1 A16]) (const_int 0 [0x0]))) 37 {*icall_value} (expr_list:REG_DEAD (reg:QI 5 r5) (expr_list:REG_EH_REGION (const_int -1 [0x]) (nil))) (expr_list:REG_DEP_TRUE (use (reg:QI 5 r5)) (expr_list:REG_DEP_TRUE (use (reg:QI 4 r4 [ D.2373 ])) (nil And r114 gets reloaded into r1: Reloads for insn # 30 Reload 0: reload_in (QI) = (symbol_ref:QI (__lshrqi3) [flags 0x41]) EIGHT_REGS, RELOAD_FOR_INPUT (opnum = 1), can't combine reload_in_reg: (reg/f:QI 114) reload_reg_rtx: (reg:QI 1 r1) Which does not satisfy the *icall_value constraints: ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c: In function ‘__mulhi3’: ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:570: error: insn does not satisfy its constraints: (call_insn/u 30 195 162 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:564 (set (reg:QI 4 r4) (call (mem:QI (reg:QI 1 r1) [0 S1 A16]) (const_int 0 [0x0]))) 37 {*icall_value} (expr_list:REG_EH_REGION (const_int -1 [0x]) (nil)) (expr_list:REG_DEP_TRUE (use (reg:QI 5 r5)) (expr_list:REG_DEP_TRUE (use (reg:QI 4 r4 [ D.2373 ])) (nil It seems that this reload doesn't pass through LEGITIMIZE_ADDRESS or LEGITIMIZE_RELOAD_ADDRESS... How can I specify here to choose an EVEN_REGS in place of the EIGHT_REGS (in fact it should choose one register in the intersection of EIGHT and EVEN_REGS) ? Thanks, -- Stelian Pop [EMAIL PROTECTED]
Re: Problem with reloading in a new backend...
(call (mem:QI (match_operand:QI 1 register_operand z)) Are you sure your z constraint only matches even numbered hard registers?
Re: Problem with reloading in a new backend...
Le jeudi 10 avril 2008 à 15:30 -0400, DJ Delorie a écrit : (call (mem:QI (match_operand:QI 1 register_operand z)) Are you sure your z constraint only matches even numbered hard registers? Well, I think so: enum reg_class { NO_REGS, BP_REGS, STACK_REGS, EIGHT_REGS, EVEN_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES }; #define N_REG_CLASSES ((int) LIM_REG_CLASSES) #define REG_CLASS_CONTENTS \ { \ { 0x }, \ { 0x0001 }, \ { 0x8000 }, \ { 0x00FF }, \ { 0x }, \ { 0x7FFE }, \ { (1LL FIRST_PSEUDO_REGISTER) - 1 }\ } ... (define_register_constraint z EVEN_REGS Even registers (r0,r2,r4, @dots{} r30)) -- Stelian Pop [EMAIL PROTECTED]
Re: Problem with reloading in a new backend...
I noticed Stack register is missing from ALL_REGS. Are registers 16bit? Is just one required for pointer? Andy
Re: Problem with reloading in a new backend...
Le jeudi 10 avril 2008 à 15:56 -0400, [EMAIL PROTECTED] a écrit : I noticed Stack register is missing from ALL_REGS. No, it is not. It is missing from GENERAL_REGS but not from ALL_REGS. Are registers 16bit? Yes. Is just one required for pointer? For now, yes, I chose to support only 2^16 RAM addresses. In fact, this microcontroller is able to address 2^24, and two registers are used for indirect accesses (Rx and Rx+1, where x is even), this is the reason why only even registers are allowed in indirect addressing... -- Stelian Pop [EMAIL PROTECTED]
Re: Problem with reloading in a new backend...
[Putting the gcc-list back in CC:, ] Le mardi 08 avril 2008 à 18:24 -0400, DJ Delorie a écrit : Do you have one insn for each pair of src/dest that movqi supports? If so, this isn't the best way to do it - you should have one insn with multiple constraint alternativess, not multiple insns. [...] reload deals with selecting among constraint options, it doesn't usually have the choice about which pattern to choose - the first that matches is used. If you have a list of patterns that all match, only the first is available to reload. Plus, reload gets confused when the predicates are used to choose among otherwise identical patterns. So, it's best to have a more general predicate (like general_operand) and use the constraints to tell reload how to implement that insn in hardware. Thanks to your suggestion, I changed my movqi pattern to look like: (define_insn *movqi [(set (match_operand:QI 0 nonimmediate_operand =r,y,y,m,r) (match_operand:QI 1 general_operand r,n,s,r,m))] { switch (which_alternative) { case 0: /* register to register */ return tfr %0,%1; case 1: /* immediate to register */ output_asm_insn (ldih %0, hi(%1), operands); output_asm_insn (ldil %0, lo(%1), operands); return ; case 2: /* immediate symbol to register */ output_asm_insn (ldih %0, hi(%c1), operands); output_asm_insn (ldil %0, lo(%c1), operands); return ; case 3: /* register to memory */ if (GET_CODE (XEXP(operands[0], 0)) == REG) { operands[0] = XEXP(operands[0], 0); return st %1,(%0); } fatal_insn (Incorrect operand:, operands[0]); case 4: /* memory to register */ if (GET_CODE (XEXP(operands[1], 0)) == REG) { operands[1] = XEXP(operands[1], 0); return ld %0,(%1); } fatal_insn (Incorrect operand:, operands[1]); } return ; } [(set_attr cc none)] ) Does this look ok ? The 'fatal_insn' should not happen, because if I see such a pattern in the define_expand movqi I force the use of a register: (define_expand movqi [(set (match_operand:QI 0 nonimmediate_operand ) (match_operand:QI 1 general_operand ))] { if (!reload_in_progress !reload_completed) { if (GET_CODE (operands[0]) == MEM (GET_CODE (operands[1]) != REG)) { operands[1] = force_reg (QImode, operands[1]); } else if (GET_CODE(operands[1]) == MEM GET_CODE(XEXP(operands[1], 0)) == PLUS GET_CODE(XEXP(XEXP(operands[1], 0), 0)) == REG GET_CODE(XEXP(XEXP(operands[1], 0), 1)) == CONST_INT) { /* indirect load */ XEXP(operands[1], 0) = force_reg (QImode, XEXP (operands[1], 0)); } else if (GET_CODE(operands[0]) == MEM GET_CODE(XEXP(operands[0], 0)) == PLUS GET_CODE(XEXP(XEXP(operands[0], 0), 0)) == REG GET_CODE(XEXP(XEXP(operands[0], 0), 1)) == CONST_INT) { /* indirect store */ XEXP(operands[0], 0) = force_reg (QImode, XEXP (operands[0], 0)); } } } ) This seems to work ok, but I still have issues at reload time, because of the base register addressing mode: in the reload pass gcc generates moves from/to the stack: Reloads for insn # 3 Reload 0: reload_in (QI) = (reg/f:QI 31 r31) EVEN_REGS, RELOAD_FOR_OPERAND_ADDRESS (opnum = 0) reload_in_reg: (reg/f:QI 31 r31) reload_reg_rtx: (reg:QI 0 r0) Reload 1: reload_out (QI) = (mem/c:QI (plus:QI (reg/f:QI 31 r31) (const_int -3 [0xfffd])) [10 S1 A16]) EVEN_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional reload_out_reg: (reg:QI 109 [ u ]) But those moves are illegal because there is no offset allowed in the base register addressing mode (see the definition of my GO_IF_LEGITIMATE_ADDRESS() ), so gcc crashes with 'unrecognizable insn'. So what's the proper way to tell that indirect addressing is allowed, but not with an offset ? Should I define an extra define_expand to deal with those insns ? Thanks again, Stelian. -- Stelian Pop [EMAIL PROTECTED]
Re: Problem with reloading in a new backend...
switch (which_alternative) { case 0: /* register to register */ Better to just use the @ syntax that gcc offers, to provide multiple patterns: @ tfr %0,%1 ldih %0, hi(%1); ldil %0, lo(%1) ldih %0, hi(%1); ldil %0, lo(%1) st %1,(%0) ld %0,(%1) Everything else should have been sorted out by the constraints. This seems to work ok, but I still have issues at reload time, because of the base register addressing mode: in the reload pass gcc generates moves from/to the stack: You might need to define LEGITIMIZE_RELOAD_ADDRESS, or at least LEGITIMIZE_ADDRESS. I don't know if reload has assumptions about such offsets, but the m32c port has a limit on the offset range so it might help you figure out your port.
Re: Problem with reloading in a new backend...
Le mercredi 09 avril 2008 à 12:41 -0400, DJ Delorie a écrit : switch (which_alternative) { case 0: /* register to register */ Better to just use the @ syntax that gcc offers, to provide multiple patterns: @ tfr %0,%1 ldih %0, hi(%1); ldil %0, lo(%1) ldih %0, hi(%1); ldil %0, lo(%1) st %1,(%0) ld %0,(%1) Everything else should have been sorted out by the constraints. Right. This seems to work ok, but I still have issues at reload time, because of the base register addressing mode: in the reload pass gcc generates moves from/to the stack: You might need to define LEGITIMIZE_RELOAD_ADDRESS, or at least LEGITIMIZE_ADDRESS. I don't know if reload has assumptions about such offsets, but the m32c port has a limit on the offset range so it might help you figure out your port. Ah, this looks exactly like what I needed, thanks! I'll try this and come back afterwards. -- Stelian Pop [EMAIL PROTECTED]
Re: Problem with reloading in a new backend...
Le mercredi 09 avril 2008 à 21:19 +0200, Stelian Pop a écrit : You might need to define LEGITIMIZE_RELOAD_ADDRESS, or at least LEGITIMIZE_ADDRESS. I don't know if reload has assumptions about such offsets, but the m32c port has a limit on the offset range so it might help you figure out your port. Ah, this looks exactly like what I needed, thanks! I'll try this and come back afterwards. Ok, I tried. Since displacements are not allowed in my addressing mode, I need to replace: (mem (plus (reg X) (const_int Y))) into (set (reg Z) (const_int Y)) (set (reg Z) (plus (reg Z) (reg X))) (mem (reg Z) This means I need to create a new pseodo register. This is allowed in LEGITIMIZE_ADDRESS but not in LEGITIMIZE_RELOAD_ADDRESS... Is there a way to do this ? Maybe I should reserve a special register for this usage (say r0). But maybe there is a better solution... Thanks, -- Stelian Pop [EMAIL PROTECTED]
Re: Problem with reloading in a new backend...
Maybe I should reserve a special register for this usage (say r0). That might be the only way, yes. Note that reload also assumes that such adds don't change the flags (i.e. a compare/jump pair must not have a flag-modifying add between them).
Problem with reloading in a new backend...
Hi, I'm working on a GCC (4.3.0) backend for a custom 16 bit microcontroller we're designing at work, and I'm facing a reload problem. After having lost many hours trying to make it work, I decided to ask for some help :) I'll try to summarize the situation below, but by all means please ask for more if something is missing. The error I'm encountering happens when compiling _divdi3 in libgcc (note that before compiling this one, several functions from libgcc compiled fine): ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c: In function ‘__divhi3’: ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1106: error: insn does not satisfy its constraints: (insn 1117 16 1118 2 ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1090 (set (reg:QI 10 r10) (const_int 24 [0x18])) 1 {*movqi_imm} (nil)) ../../../../src/gcc-4.3.0/libgcc/../gcc/libgcc2.c:1106: internal compiler error: in reload_cse_simplify_operands, at postreload.c:395 The microcontroller in question is a 16 bit one, and addresses the memory only in 16 bit words: #define BITS_PER_UNIT 16 #define UNITS_PER_WORD 1 This microcontroller has 32 hard registers. Immediate constants can only be loaded into the first 8 registers. There are no index registers. All the even registers can serve as a base register. However, the base register addressing is reduced to its simplest form, where the offset is always 0. Based on the above, I have defined: enum reg_class { NO_REGS, STACK_REGS, EIGHT_REGS, EVEN_REGS, ALL_REGS, LIM_REG_CLASSES }; #define GENERAL_REGS ALL_REGS ... #define REG_CLASS_CONTENTS \ { \ { 0x }, \ { 0x8000 }, \ { 0x00FF }, \ { 0x }, \ { (1LL FIRST_PSEUDO_REGISTER) - 1 }\ } #define REGNO_REG_CLASS(REGNO) \ ((REGNO) 30 ? STACK_REGS \ : (REGNO) 8 ? EIGHT_REGS \ : (REGNO % 2) == 0 ? EVEN_REGS \ : GENERAL_REGS) #define BASE_REG_CLASS EVEN_REGS #define INDEX_REG_CLASS NO_REGS #define REGNO_OK_FOR_BASE_P(NUM) (NUM % 2 == 0) #define REGNO_OK_FOR_INDEX_P(NUM) 0 #define PREFERRED_RELOAD_CLASS(X, CLASS)\ ((CONSTANT_P(X)) ? EIGHT_REGS : \ (MEM_P(X)) ? EVEN_REGS : CLASS) #define PREFERRED_OUTPUT_RELOAD_CLASS(X, CLASS) \ ((CONSTANT_P(X)) ? EIGHT_REGS : \ (MEM_P(X)) ? EVEN_REGS : CLASS) ... #define STACK_POINTER_REGNUM 31 #define FRAME_POINTER_REGNUM 30 #ifdef REG_OK_STRICT #define REG_OK_FOR_BASE_P(X)\ (REGNO_OK_FOR_BASE_P (REGNO (X)) (REGNO (X) FIRST_PSEUDO_REGISTER)) #else #define REG_OK_FOR_BASE_P(X)\ (REGNO_OK_FOR_BASE_P (REGNO (X)) || REGNO (X) = FIRST_PSEUDO_REGISTER) #endif #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL)\ do {\ if (GET_CODE (X) == REG (REG_OK_FOR_BASE_P(X)))\ goto LABEL; \ else if (GET_CODE(X) == PLUS\ REG_OK_FOR_BASE_P (XEXP (X, 0))\ GET_CODE(XEXP(X,1)) == CONST_INT \ INTVAL(XEXP(X,1)) == 0) \ goto LABEL; \ } while (0) I also defined some constraints for the register classes: (define_register_constraint x STACK_REGS Stack registers (r30--r31)) (define_register_constraint y EIGHT_REGS Low eight registers (r0--r7)) (define_register_constraint z EVEN_REGS Even registers (r0,r2,r4, @dots{} r30)) The movqi_imm pattern which constraints doesn't match has been defined with (note the 'y' constrant): (define_insn *movqi_imm [(set (match_operand:QI 0 register_operand =y) (match_operand:QI 1 const_int_operand ))] { output_asm_insn (ldih %0, hi(%1), operands); output_asm_insn (ldil %0, lo(%1), operands); return ; } [(set_attr cc none)] ) Now, I'm trying to figure out why the error happens, with GCC choosing to put an immediate into r10 instead of an EIGHT_REGS. It all seems to come (I do not know why) from insn 16 in libgcc2.c.175r.lreg: Register 453 costs: EIGHT_REGS:0
Re: Problem with reloading in a new backend...
Take at look at AVR target which is very similar. Here onluy d constrained register accept constants (they are call used registers too) The AVR move pattern (*reloadinqi) has multiple constrain options d against i being relevant. So check you have all the combinations defined. You omitted i constraint but I dont know if that is relevant. When costing is done, it walks thru constraints. You don't seem to have many constrain combinations (since costs are lower than I typically see for AVR). It will score on both EVEN and EIGHT and likely pick EVEN because its bigger class. So I think that is perhaps reason. I think order of classes maybe need to be changed or something else to prevent problem with overlap (LOWER_EVEN? UPPER_EVEN) But I could be completely wrong! Andy