This is the mail archive of the gcc-patches@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: [m68k] Fix and improve ColdFire function prologue/epilogue generation(respin)


Richard Henderson wrote:
On Wed, Sep 03, 2003 at 11:32:58PM +0200, Bernardo Innocenti wrote:

+  if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+    return 0;


Intuitively, this is wrong.  I can see how it worked before, but
not after your change.

Actually, it works fine with and without -fomit-frame-pointer. The reason is probably that GCC never invokes that function to eliminate the ARG_POINTER_REGNUM from HARD_FRAME_POINTER_REGNUM.

When I first tested that code, I added some big constants
(1000, 2000, 3000 and 4000) and looked at the asm output produced
with several options.

I think the correct value should be:

 if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
   return (frame_pointer_needed ? -UNITS_PER_WORD * 2 : -UNITS_PER_WORD);

The first case skips both the return address and the saved fp,
while the second skips only the return address.

To wit:

m68k.h:#define FIRST_PARM_OFFSET(FNDECL) 8

That says that the offset from ARG_POINTER_REGNUM to the first
actual argument is 8.  Which, when you have a frame pointer, is
exactly right for m68k -- four bytes for saved frame pointer,
and four bytes for saved return address.

What does GCC use that for? Its value gets assigned to the static variable `in_arg_offset' at function entry time and seems to be only used in instantiate_new_reg().


With -fomit-frame-pointer, however, things get screwy.  The fact
that we have a hard-coded 8 above is arguably a bug.

...a bug I'm afraid to fix until I've grasped what the consequences are :-)


It appears as if things were worked around by adding magic
constants,

- asm_fprintf (stream, "\tsubq.w %I%wd,%Rsp\n", fsize + 4);

like so.


You've not preserved this bit of, ahem, style, and so as far as
I can see, you've broken parameter passing without a frame pointer.

No, it works fine indeed. Tested with a full build of Linux kernel and userland!

There must be some other way of computing offsets to the arguments.


The correct way to do this is to make the argument pointer point
to the arguments.  Then you do

  if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
    return 8;

Ok, that's what I'm doing in the code above, taking care of frame_pointer_needed too.


  if (from == ARG_POINTER_REGNUM && to == STACK_FRAME_POINTER_REGNUM)
    return stack_size + 4;

What's STACK_FRAME_POINTER_REGNUM? :-)


If you meant STACK_POINTER_REGNUM, that combo is already handled
correctly here:

if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
   return frame.offset + frame.size +
     (frame_pointer_needed ? -UNITS_PER_WORD * 2 : -UNITS_PER_WORD);

If you meant FRAME_POINTER_REGNUM, that pair is not included in
ELIMINABLE_REGS, not even in the i386 back-end.

--
 // Bernardo Innocenti - Develer S.r.l., R&D dept.
\X/  http://www.develer.com/

Please don't send Word attachments - http://www.gnu.org/philosophy/no-word-attachments.html




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