Hi,

I am doing a port in GCC 4.5.1. For the port

1. there is only (reg + offset) addressing mode only when reg is SP.
Other base registers are not allowed
2. FP cannot be used as a base register. (FP based addressing is done
by copying it into a base register)

In order to take advantage of FP elimination (this will create SP +
offset addressing), what i did the following

1. Created a new register class (address registers + FP) and used this
new class as the BASE_REG_CLASS
2. Defined HARD_REGNO_OK_FOR_BASE_P like the following :

#define HARD_REGNO_OK_FOR_BASE_P(NUM) \
    ((NUM) < FIRST_PSEUDO_REGISTER \
     && (((reload_completed || reload_in_progress)? 0 : (NUM) == FP_REG) \
         || REGNO_REG_CLASS(NUM) == ADD_REGS))

3. In legitimate_address_p i have the followoing:

      if (REGNO (x) == FP_REG)
        {
          if (strict)
            return false;
          else
            return true;
        }
      else if (strict)
        return STRICT_REG_OK_FOR_BASE_P (REGNO (x));
      else
        return NONSTRICT_REG_OK_FOR_BASE_P (REGNO (x));

But when FP doesn't get eliminated i will get address of the form

(plus:QI (reg/f:QI 27 as15) (const_int 2))

which gets reloaded by replacing FP with address register, other than
SP. I am guessing this happens because of modified BASE_REG_CLASS. I
haven't confirmed this. So in order to over come this what i have done
is, in legitimize_reload_address i have the following :

  if (GET_CODE (*x) == PLUS
      && REG_P (XEXP (*x, 0))
      && REGNO (XEXP (*x, 0)) < FIRST_PSEUDO_REGISTER
      && GET_CODE (XEXP (*x, 1)) == CONST_INT
      && XEXP (*x, 0) == frame_pointer_rtx)
    {
       /* GCC will by default reload the FP into a BASE_CLASS_REG,
          which results in an invalid address.  For us, the best
          thing to do is move the whole expression to a REG.  */
      push_reload (*x, NULL_RTX, x, NULL, SPAA_REGS,
                   mode, VOIDmode,0, 0, opnum, (enum reload_type)type);
      return 1;
    }

Does my logic makes sense? Is there any better way to implement this?

With this implementation for the following sequence :

(insn 9 6 10 2 fun_calls.c:12 (set (reg/f:QI 42)
        (mem/f/c/i:QI (plus:QI (reg/f:QI 33 AP)
                (const_int -2 [0xfffffffffffffffe])) [0 f+0 S1 A32]))
9 {movqi_op} (nil))

(insn 10 9 11 2 fun_calls.c:12 (set (reg:QI 43)
        (const_int 60 [0x3c])) 7 {movqi_op} (nil))

I am getting the following output:

(insn 45 6 47 2 fun_calls.c:12 (set (reg:QI 28 a0)
        (const_int 2 [0x2])) 9 {movqi_op} (nil))

(insn 47 45 48 2 fun_calls.c:12 (set (reg:QI 28 a0)
        (reg/f:QI 27 as15)) 9 {movqi_op} (nil))

(insn 48 47 49 2 fun_calls.c:12 (set (reg:QI 28 a0)
        (plus:QI (reg:QI 28 a0)
            (const_int 2 [0x2]))) 14 {addqi3} (expr_list:REG_EQUIV
(plus:QI (reg/f:QI 27 as15)
            (const_int 2 [0x2]))
        (nil)))

(insn 49 48 10 2 fun_calls.c:12 (set (reg/f:QI 0 g0 [42])
        (mem/f/c/i:QI (reg:QI 28 a0) [0 f+0 S1 A32])) 9 {movqi_op} (nil))

insn 45 is redundant. Is this generated because the
legitimize_reload_address is wrong?

Any hints as to why the redundant instruction gets generated?

Regards,
Shafi

Reply via email to