Re: Problem with reloading in a new backend...

2008-04-15 Thread Stelian Pop

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...

2008-04-14 Thread Stelian Pop

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...

2008-04-14 Thread Jim Wilson

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...

2008-04-11 Thread Jim Wilson

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...

2008-04-11 Thread Stelian Pop

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...

2008-04-11 Thread Jim Wilson
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...

2008-04-11 Thread Jim Wilson

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...

2008-04-10 Thread Stelian Pop

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...

2008-04-10 Thread Stelian Pop

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...

2008-04-10 Thread DJ Delorie

   (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...

2008-04-10 Thread Stelian Pop

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...

2008-04-10 Thread hutchinsonandy

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...

2008-04-10 Thread Stelian Pop

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...

2008-04-09 Thread Stelian Pop
[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...

2008-04-09 Thread DJ Delorie

 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...

2008-04-09 Thread Stelian Pop

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...

2008-04-09 Thread Stelian Pop

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...

2008-04-09 Thread DJ Delorie

 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...

2008-04-08 Thread Stelian Pop
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...

2008-04-08 Thread Andy H

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