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]

Problems with register elimination


I am having a great deal of trouble getting register elimination (and
stack frame layouts in general) working properly on my architecture.
There is some fundamental issue I'm simply not getting here.

My architecture is a fairly vanilla RISC system with a link pointer. The
stack frame layout I'm aiming for looks like this:

  hi   incoming_params
       ================== ap
       callee_saves
       ------------------
       local_vars
       local_vars_padding
       ------------------ fp
       outgoing_params
  lo   ------------------ sp

The docs says that because I don't know where the locals are until I
know how big callee_saves is, I have to use the following setup:

#define STACK_POINTER_REGNUM SP_REG
#define FRAME_POINTER_REGNUM FP_REG /* virtual frame pointer */
#define HARD_FRAME_POINTER_REGNUM R6_REG /* real frame pointer */
#define ARG_POINTER_REGNUM AP_REG /* virtual argument pointer */

AP_REG and FP_REG are fake registers (values 27 and 28 respectively;
different from R6_REG and SP_REG). These get eliminated into either the
stack or r6 as follows:

#define ELIMINABLE_REGS	\
{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
 { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
 { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
 { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }}

This is all utterly standard, and mostly stolen from other ports...
except I can't make it work, in various weird ways.

Weirdness (1): I never see ARG_POINTER_REGNUM used to access arguments.
The compiler seems to want to access function arguments via
FRAME_POINTER_REGNUM plus a small value, which means they overlap the
locals. (It's definitely using the same numeric ranges. It looks like
it's trying to use ARG_POINTER_REGNUM but is getting the wrong register.)

Weirdness (2): the following test function generates code with tries to
copy AP_REG into a register without eliminating it.

void* return_local(void) { int i; return &i; }

It turns into the following RTL:

(insn 17 2 12 2 (set (reg/i:SI 0 r0)
        (reg:SI 27 ?ap)) test.c:14 4
     (nil))
(insn 12 17 15 2 (use (reg/i:SI 0 r0)) test.c:14 -1
     (nil))

Why isn't elimination happening in this situation? And why is AP_REG
being used here at all?

I've been looking at the various backends, but they're not very helpful
--- they're all rather different, and I can't see anything they're doing
which I'm not or vice versa.

However, I am particularly perturbed by the following comment from the
MCore port:

/* Note that the name `fp' is horribly misleading since `fp' is in fact
   only the argument-and-return-context pointer. */

I don't know whether this is just talking about the MCore, or gcc in
general --- I find it interesting that most backends which use a fake
frame pointer seem to end up with FRAME_POINTER_REGNO and
HARD_FRAME_POINTER_REGNO pointing at different addresses.

If anyone can offer any suggestions as to what I'm doing wrong --- or,
better still, point me at more in-depth reading on how all this is
supposed to work!

-- 
ââââ ïïïïïïïïïïïïïï âââââ http://www.cowlark.com âââââ
â "Every planet is weird. I spent six weeks on a moon where the
â principal form of recreation was juggling geese. Baby geese. Goslings.
â They were juggled." --- Firefly, _Our Mrs. Reynolds_

Attachment: signature.asc
Description: OpenPGP digital signature


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