public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Re^2: Restricted addressing modes in ColdFire FPU for DFmode
@ 2001-12-07 17:35 Peter Barada
  2001-12-08 22:46 ` Richard Henderson
  0 siblings, 1 reply; 9+ messages in thread
From: Peter Barada @ 2001-12-07 17:35 UTC (permalink / raw)
  To: gcc; +Cc: Peter.Barada


>>I'm working on adding the V4E ColdFire FPU instructions to gcc-2.95.3,
>>and I've been having a very hard time convincing gcc to deal with the
>>restricted addressing modes that the ColdFire FPU supports.

With the previous changes that I've made to add a cannot_combine flag
to tell the cominber that it shouldn't combine the following:

(insn 8 6 9 (set (reg:SI 31)
        (symbol_ref:SI ("zat"))) -1 (nil)
    (expr_list:REG_EQUAL (symbol_ref:SI ("zat"))
        (nil)))

(insn/C 9 8 11 (set (reg:DF 30)
        (mem:DF (reg:SI 31) 0)) -1 (nil)
    (nil))


Everything works(at least for adddf3, subdf3, muldf3, divdf3, negdf2,
etc)  Note the "/C" on the memory reference which indicates that the
'cannot_combine' bit in the RTX is set whihc tells
cant_combine_insn_p() to return 1 early.  

Now I'm trying to deal with the other side which is storing the value
back to memory.  Here's the result of yy.c.lreg for a store:

(insn 10 16 11 (set (reg:SI 30)
        (symbol_ref:SI ("zat"))) 47 {cfv4_movsi} (nil)
    (expr_list:REG_EQUIV (symbol_ref:SI ("zat"))
        (nil)))

(insn/C 11 10 0 (set (mem/f:DF (symbol_ref:SI ("zat")) 0)
        (mem:DF (reg:SI 30) 0)) 67 {movdf_v4e} (insn_list 10 (nil))
    (expr_list:REG_DEAD (reg:SI 30)
        (nil)))


Since its survived the combiner, I'd expect everything to be happy and
to match up with my machine description quite well, but somewhere
between here and where it dumps yy.c.greg, it dies with(and the
traceback of): 

/tmp/yy.c: In function `a':
/tmp/yy.c:5: internal error--insn does not satisfy its constraints:

(insn 20 11 17 (set (mem/f:DF (symbol_ref:SI ("zat")) 0)
        (reg:DF 16 %fp0)) 67 {movdf_v4e} (nil)
    (nil))

(gdb) where
#0  exit (status=33) at exit.c:40
#1  0x0804944e in fatal_insn ()
    at /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-2.95.3/gcc/toplev.c:1480
#2  0x0804947e in fatal_insn_not_found ()
    at /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-2.95.3/gcc/toplev.c:1494
#3  0x08133ecc in reload_cse_simplify_operands (insn=0x81df5c8)
    at /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-2.95.3/gcc/reload1.c:9245
#4  0x08133873 in reload_cse_regs_1 (first=0x81e0fec)
    at /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-2.95.3/gcc/reload1.c:8903
#5  0x08133ad0 in reload_cse_regs (first=0x81e0fec)
    at /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-2.95.3/gcc/reload1.c:9014
#6  0x0804c78f in rest_of_compilation (decl=0x81eeea4)
    at /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-2.95.3/gcc/toplev.c:4204
#7  0x0816fcb5 in finish_function (nested=0)
    at /home/pbarada/work/cvs-wavemark/cross-linux-tools/gcc-2.95.3/gcc/c-decl.c:7270


With the RTL looking like:

(define_expand "movdf"
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
	(match_operand:DF 1 "nonimmediate_operand" ""))]
  ""
  "
{
  rtx insn;
  int cannot_combine = FALSE;

  if (TARGET_FPU_V4E) {
    /* The ColdFire FPU can't deal with absolute addresses or double
     * constants, so push it to memory */
    if (CONSTANT_P (operands[1])) {
      operands[1] = force_const_mem(DFmode, operands[1]);
      if (! memory_address_p (DFmode, XEXP (operands[1], 0))
	  && ! reload_in_progress)
	operands[1] = change_address (operands[1], DFmode,
				      XEXP (operands[1], 0));
    }
    /* Since the Coldfire can't deal with absolute addresses, force
     * the address of the reference into a register and do it indirect */
    if (!reload_in_progress) {
      if (GET_CODE (operands[0]) == MEM
          && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) {
        operands[1] = gen_rtx (MEM, DFmode,
                             force_reg (Pmode, XEXP (operands[0], 0)));
        cannot_combine = TRUE;
      }
      if (GET_CODE (operands[1]) == MEM
          && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) {
        operands[1] = gen_rtx (MEM, DFmode,
                             force_reg (Pmode, XEXP (operands[1], 0)));
        cannot_combine = TRUE;
      }
      if (cannot_combine) {
        /* Set RTX_CANNOT_COMBINE to prevent the combiner from putting
         this back together, but only on the insn, not the operand! */
        insn = emit_insn(gen_rtx_SET(VOIDmode, operands[0], operands[1]));
        RTX_CANNOT_COMBINE_P(insn) = 1;
        DONE;
      }
    }
  }
}")

(define_insn "movdf_v4e"
  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,<Q>S")
	(match_operand:DF 1 "nonimmediate_operand" "f<Q>S,f"))]
  "TARGET_FPU_V4E"
  "*
{
  return \"fmove%.d %1,%0\";
}")


Note that 'Q' is register indirect, and 'S' is register indirect with
offset, both of which are allowed by the Coldfire FPU.  I thought the
combining pass was the only one to paste instructions together.  What
am I missing and how best can I convince gcc to use register indirect
to store the DP register to memory?

Thanks for any advice.

-- 
Peter Barada                                   Peter.Barada@motorola.com
Wizard                                         781-852-2768 (direct)
WaveMark Solutions(wholly owned by Motorola)   781-270-0193 (fax)

^ permalink raw reply	[flat|nested] 9+ messages in thread
* Re: Restricted addressing modes in ColdFire FPU for DFmode
@ 2001-12-07 10:13 Peter Barada
  2001-12-07 11:27 ` Alan Lehotsky
  0 siblings, 1 reply; 9+ messages in thread
From: Peter Barada @ 2001-12-07 10:13 UTC (permalink / raw)
  To: gcc; +Cc: Peter.Barada


I'm working on adding the V4E ColdFire FPU instructions to gcc-2.95.3,
and I've been having a very hard time convincing gcc to deal with the
restricted addressing modes that the ColdFire FPU supports.

The fmove.d instruction supports only the following addressing modes:
predecrement, postincement, indirect, inderect with offset, and
pc-relative with offset(for loads).  Note that neither register direct
nor absolute addressing is supported.  I created to following RTL for
movdf:

(define_expand "movdf"
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
	(match_operand:DF 1 "general_operand" ""))]
  ""
  "
{
  if (TARGET_FPU_V4E) {
    /* The ColdFire FPU can't deal with absolute addresses or double
     * constants, so push the constant to memory */
    if (CONSTANT_P (operands[1])) {
      operands[1] = force_const_mem (DFmode, operands[1]);
      if (! memory_address_p (DFmode, XEXP (operands[1], 0))
	  && ! reload_in_progress)
	operands[1] = change_address (operands[1], DFmode,
				      XEXP (operands[1], 0));
    }
    /* Since the Coldfire can't deal with absolute addresses, force
     * the address of the reference into a register and do it indirect */
    if (!reload_in_progress && GET_CODE (operands[1]) == MEM
        && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
      operands[1] = gen_rtx (MEM, DFmode,
                             force_reg (Pmode, XEXP (operands[1], 0)));
  }
}")

(define_insn "movdf_v4e"
  [(set (match_operand:DF 0 "general_operand" "=f,<Q>S")
	(match_operand:DF 1 "general_operand" "f<Q>S,f"))]
  "TARGET_FPU_V4E"
  "*
{
  return \"fmove%.d %1,%0\";
}")


And that split up symbolic addressing quite well(as well as handled constants):

(insn 8 6 9 (set (reg:SI 30)
        (symbol_ref/u:SI ("*.LC0"))) -1 (nil)
    (expr_list:REG_EQUAL (symbol_ref/u:SI ("*.LC0"))
        (nil)))

(insn 9 8 10 (set (reg/i:DF 16 %fp0)
        (mem:DF (reg:SI 30) 0)) -1 (nil)
    (nil))

but the combiner converted that back into:

(insn 9 8 10 (set (reg/i:DF 16 %fp0)
        (mem:DF (symbol_ref/u:SI ("*.LC0")) 0)) 67 {movdf_v4e} (nil)
    (expr_list:REG_EQUAL (const_double:DF (mem/u:DF (symbol_ref/u:SI ("*.LC0")) 0) 0 [0x0] 0 [0x0] 1073643520 [0x3ffe8000])
        (nil)))

Which died with:

/tmp/z.c: In function `x':
/tmp/z.c:5: internal error--insn does not satisfy its constraints:

(insn 21 8 9 (set (reg:DF 17 %fp1)
        (mem:DF (symbol_ref/u:SI ("*.LC0")) 0)) 67 {movdf_v4e} (nil)
    (nil))



I looked over combine.c, and I didn't see anyway that a target can
prevent combination from happening.  So in desperation I decided to
add a flag to the rtx struct:

  /* 1 in an INSN or a SET if this rtx can *not* be combined with
     either RTX next to it.  Its necessary to limit the combiner from
     creating RTX that the machine description worked very hard to
     keep seperate */
  unsigned cannot_combine : 1;


And its access macro:

#define RTX_CANNOT_COMBINE_P(RTX) ((RTX)->cannot_combine)


As well as modify the initializer of global_rtl to add the extra zero...
And then added the following statment to cant_combine_insn_p():

  /* For particular chips with restrictive addressing modes, the
     machine description may split up accesses and then mark the
     instruction.  As an example the ColdFire FPU can't deal with
     absolute addressing, but the ColdFire integer unit can, so the
     m68k.md forces the symbol_ref into a register and uses indirect
     addressing, and marks the instruction as one that can't be
     combined. */
  if (RTX_CANNOT_COMBINE_P (insn))
    return 1;


As well as changed the movdf pattern to:

(define_expand "movdf"
  [(set (match_operand:DF 0 "nonimmediate_operand" "")
	(match_operand:DF 1 "general_operand" ""))]
  ""
  "
{
  rtx insn;

  if (TARGET_FPU_V4E) {
    /* The ColdFire FPU can't deal with absolute addresses or double
     * constants, so push it to memory */
    if (CONSTANT_P (operands[1])) {
      operands[1] = force_const_mem (DFmode, operands[1]);
      if (! memory_address_p (DFmode, XEXP (operands[1], 0))
	  && ! reload_in_progress)
	operands[1] = change_address (operands[1], DFmode,
				      XEXP (operands[1], 0));
    }
    /* Since the Coldfire can't deal with absolute addresses, force
     * the address of the reference into a register and do it indirect */
    if (!reload_in_progress && GET_CODE (operands[1]) == MEM
        && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) {
      operands[1] = gen_rtx (MEM, DFmode,
                             force_reg (Pmode, XEXP (operands[1], 0)));
      /* Create the instruciton and set RTX_CANNOT_COMBINE_P to
         prevent the combiner from putting this back together.
      insn = emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
      RTX_CANNOT_COMBINE_P (insn) = 1;
      DONE;
    }
  }
}")


Now the following code:

double x(void)
{
  return 0.5;
}

Compiles into:

	.file	"z.c"
gcc2_compiled.:
.section	.rodata
	.align 	2
.LC0:
	.double 0r5.00000000000000000000e-1
.text
.globl x
	.type	 x,@function
x:
	link.w %a6,#0
	lea .LC0,%a0
	fmove.d (%a0),%fp0
	unlk %a6
	rts

Which looks correct.


My question to you all is whether or not this is a viable approach.
Does anyone have a suggestion for how better to solve this problem?

Thanks in advance for your guidance,

-- 
Peter Barada                                   Peter.Barada@motorola.com
Wizard                                         781-852-2768 (direct)
WaveMark Solutions(wholly owned by Motorola)   781-270-0193 (fax)

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2001-12-10 22:35 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-12-07 17:35 Re^2: Restricted addressing modes in ColdFire FPU for DFmode Peter Barada
2001-12-08 22:46 ` Richard Henderson
2001-12-10  8:15   ` Peter Barada
2001-12-10 13:11     ` Richard Henderson
2001-12-10 13:59       ` Peter Barada
2001-12-10 15:06         ` Peter Barada
  -- strict thread matches above, loose matches on Subject: below --
2001-12-07 10:13 Peter Barada
2001-12-07 11:27 ` Alan Lehotsky
2001-12-07 13:01   ` Peter Barada

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).