This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Reload problems with only one base reg for "base + offset" addressing mode


Hi,

I am porting GCC to a 8bit architecture, and now I have problem on
reload problem on addressing mode.
Besides 15 general registers, it has three 16bit address registers,
R16,R17,R18.
R16,R17,R18 are able to be as base register in "base" address mode,
but only R18 can be base regs for "base+offse(immediate)t" address
mode.
I make "BASE_REGS" class  for "R16,R17,R18", and "POINTER_REG" class
for R18, and frame pointer is R18, the maxim "offset" in "base+offset"
is 127.

And now the test compiler sometimes generate following errors:

test3.c: In function 'OS_EventTaskWait':
test3.c:62: error: unable to find a register to spill in class 'POINTER_REG'
test3.c:62: error: this is the insn:
(insn 58 57 61 2 (set (mem/s:QI (plus:HI (reg:HI 16 R16 [51])
                (const_int 5 [0x5])) [0 <variable>.OSEventTbl S1 A8])
        (ior:QI (mem/s:QI (plus:HI (reg:HI 16 R16 [51])
                    (const_int 5 [0x5])) [0 <variable>.OSEventTbl S1 A8])
            (mem/s:QI (plus:HI (reg:HI 17 R17 [orig:38 OSTCBCur.0 ] [38])
                    (const_int 14 [0xe])) [0 <variable>.OSTCBBitX+0 S1
A8]))) 25 {*iorqi3_noimm} (insn_list:REG_DEP_TRUE 51 (nil))
    (expr_list:REG_DEAD (reg:HI 17 R17 [orig:38 OSTCBCur.0 ] [38])
        (expr_list:REG_DEAD (reg:HI 16 R16 [51])
test3.c:62: confused by earlier errors, bailing out.

It seems that the reload tries to reload "R16+5" and "R17+114" to be
"R18+5" and "R17+14", but complains that there is only on R18.

I have constraint the base reg of "base+offset(immediate)" address
mode in "GO_IF_LEGITIMATE_ADDRESS", and defined
LEGITIMIZE_RELOAD_ADDRESS (I take reference from AVR port).

#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)    \
do                                                 \
{									                        \
   debug_rtx(X);                                   \
   printf("LEGITIMIZE_RELOAD_ADDRESS,frame ptr
needed=%d\r\n",frame_pointer_needed);\
   if (GET_CODE (X) == PLUS						      \
   && REG_P (XEXP (X, 0))						         \
   && GET_CODE (XEXP (X, 1)) == CONST_INT				                      \
   && INTVAL (XEXP (X, 1)) >= 1)					                              \
   {									                                             \
      int fit = INTVAL (XEXP (X, 1)) <= (127 - GET_MODE_SIZE (MODE));	    \
      if (fit )								                                          \
      {\
         if( !FRAME_POINTER_REQUIRED )	   \
         {  						                                                \
            if (reg_equiv_address[REGNO (XEXP (X, 0))] != 0)		               \
            {								                                             \
   	         int regno = REGNO (XEXP (X, 0));				                              \
               rtx mem = make_memloc (X, regno);				                     \
               push_reload(XEXP (mem,0), NULL, &XEXP (mem,0), NULL,
          \
                           BASE_REGS, Pmode, VOIDmode, 0, 0,		
         \
                           1, ADDR_TYPE (TYPE));			                  \
               push_reload(mem, NULL_RTX, &XEXP (X, 0), NULL,		    \
                          POINTER_REG, GET_MODE (X), VOIDmode, 0, 0, \
                           OPNUM, TYPE);				    \
               goto WIN;							    \
            }								             \
            push_reload(XEXP (X, 0), NULL_RTX, &XEXP (X, 0), NULL,	       \
                      POINTER_REG, GET_MODE (X), VOIDmode, 0, 0,	    \
                      OPNUM, TYPE);					\
            goto WIN;							      \
         }\
         else\
         {\
            push_reload (X, NULL_RTX, &X, NULL,				    \
                    BASE_REGS, GET_MODE (X), VOIDmode, 0, 0,	    \
                     OPNUM, TYPE);					    \
            goto WIN;							    \
         }\
      }								               \
      else if (! (frame_pointer_needed && XEXP (X,0) == frame_pointer_rtx)) \
      {								                            \
         push_reload (X, NULL_RTX, &X, NULL,				    \
                     BASE_REGS, GET_MODE (X), VOIDmode, 0, 0,	    \
                     OPNUM, TYPE);					    \
         goto WIN;							    \
      }								    \
   }									    \
} while(0)

Does this port will suffer from reload hell as there is only one
offset-able base register? Or can  I do some constraints that there is
only one offset-able memory operand in insn patterns?

Any suggestion is appreciated.
Thank you for your guys.

Jiang.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]