This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Pseudo register replaced by a symbol_ref
- From: Peter Barada <pbarada at mail dot wm dot sps dot mot dot com>
- To: aaadland at atmel dot no
- Cc: gcc at gcc dot gnu dot org
- Date: Mon, 28 Jul 2003 15:00:38 -0400
- Subject: Re: Pseudo register replaced by a symbol_ref
- References: <oprsvcw8mscuup6n@store>
>In my port I can't load from a symbol_ref. Because of this the pattern
>(set (reg:DF 25)
> (mem:DF (symbol_ref:SI ("*LLC0"))))
>is replaced by a
>(set (reg:DF 25)
> (mem:DF (reg:SI 38)))
>in movdf using force_reg. The problem is that if GCC can't find a hard
>register for this pseudo it is replacing it with a symbol_ref again. This
>is done in find_reloads() in reload.c:2687 (version 3.2.3). How can I tell
>GCC that it can't do that?
>
>In the documentation, I have read that the strict version of
>GO_IF_LEGATIMATE_ADDRESS has to handle a pseudo register as a memory
>reference. reload.c is using the strict version. Do I have to handle it as
>a potensial symbol_ref too?
This sounds exactly like the problem I had trying to get the ColdFire v4e
to deal with floating point operands that are in memory. The ColdFire
v4e can not use a symbol_ref as an addressing mode for an FPU
instruction.
To fix this, I had to mess with both what defines a valid addressing
mode(as well as howit is legitimized, as well as reload machinery).
I had to mess with GO_IF_LEGITIMATE_ADDRESS to reject
float modes being refered to through a symbol_ref:
/* In Coldfire v4e and float mode, only accept addressing modes 2-5 */
#define GO_IF_CFV4E_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ if (LEGITIMATE_BASE_REG_P(X) \
|| ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
&& LEGITIMATE_BASE_REG_P (XEXP (X, 0))) \
|| ((GET_CODE (X) == PLUS) && LEGITIMATE_BASE_REG_P (XEXP (X, 0)) \
&& (GET_CODE (XEXP (X, 1)) == CONST_INT) \
&& ((((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x100000)))) \
goto ADDR;}
/* If pic, we accept INDEX+LABEL, which is what do_tablejump makes. */
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ if (TARGET_CFV4E && (GET_MODE_CLASS (MODE) == MODE_FLOAT)) \
{ GO_IF_CFV4E_LEGITIMATE_ADDRESS(MODE, X, ADDR); \
} else { \
GO_IF_NONINDEXED_ADDRESS (X, ADDR); \
GO_IF_INDEXED_ADDRESS (X, ADDR); \
if (flag_pic && MODE == CASE_VECTOR_MODE && GET_CODE (X) == PLUS \
&& LEGITIMATE_INDEX_P (XEXP (X, 0)) \
&& GET_CODE (XEXP (X, 1)) == LABEL_REF) \
goto ADDR; } }
I also had to mess with reloads machinery by defined
SECONDARY_RELOAD_CLASS:
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly
NO_REGS is returned.
Avoid doing any work for the common case calls. */
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
secondary_reload_class(CLASS, MODE, IN)
where the code looked like:
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
enum reg_class
secondary_reload_class (class, mode, in)
enum reg_class class;
enum machine_mode mode;
rtx in;
{
int regno = -1;
enum rtx_code code = GET_CODE (in);
if (!TARGET_CFV4
|| (mode != SFmode && mode != DFmode))
return NO_REGS;
if (! CONSTANT_P (in))
{
regno = true_regnum (in);
/* A pseudo is the same as memory. */
if (regno == -1 || regno >= FIRST_PSEUDO_REGISTER)
code = MEM;
}
/* If we want to move a CONST_DOUBLE or a symbolic memory operand to/from
a FP_REG, then use ADDR_REGS as the intermediary */
if (class == FP_REGS &&
(code == CONST_DOUBLE || (code == MEM && (symbolic_operand(in, mode)))))
return ADDR_REGS;
return NO_REGS;
}
I also had to define the patters reload_insf, reload_outsf,
reload_indf, reload_outdf
(define_expand "reload_indf"
[(set (match_operand:DF 0 "nonimmediate_operand" "=f")
(match_operand:DF 1 "general_operand" "mf"))
(clobber (match_operand:SI 2 "register_operand" "=&a"))]
"TARGET_CFV4E"
"
{
if (emit_move_sequence (operands, DFmode, operands[2]))
DONE;
/* We don't want the clobber emitted, so handle this ourselves. */
emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
DONE;
}")
Where emit_move_sequence() was stolen from the gcc/config/hppa/hppa.c
and modified as necessary. I used the hppa as the model for how to
deal with this type of restriction.
Good Luck!
--
Peter Barada Peter.Barada@motorola.com
Wizard 781-852-2768 (direct)
WaveMark Solutions(A Motorola Company) 781-270-0193 (fax)