Help with reloading FP + offset addressing mode
Mohamed Shafi
shafitvm@gmail.com
Thu Oct 28 14:24:00 GMT 2010
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
More information about the Gcc
mailing list