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]

Re: Pseudo register replaced by a symbol_ref


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


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