This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Liberating structs from memory
- To: Greg McGary <greg at mcgary dot org>
- Subject: Re: Liberating structs from memory
- From: Jeffrey A Law <law at cygnus dot com>
- Date: Fri, 18 Aug 2000 16:23:04 -0600
- cc: gcc at gcc dot gnu dot org
- Reply-To: law at cygnus dot com
In message <200008182034.NAA16501@kayak.mcgary.org>you write:
> I wish to begin discussion about how to improve gcc's handling of auto
> variable structs whose address is never taken. Such structs need not
> reside in memory, and would be better treated as if all members were
> separate variables, individually assignable to registers.
Yup. This is commonly referred to as scalar replacement of aggregates and
typically happens relatively early in the compilation process.
I think this is most easily done at the tree level -- except that we do not
have functions as trees for most of the front-ends yet, so it's hard to know
if an auto has had its address taken until its too late.
> Special consideration must be given to structs passed (and returned)
> by value. On RISC machines, such structs need to be spilled to a
> temporary in memory and the address of the temporary passed to the
> callee. Similar for return values: the caller allocates an in-memory
> temporary and passes a hidden first argument with its address. The
> callee stuffs the return value into memory at that address. A naive
> first implementation should probably consider a struct passed by value
> as one whose address is taken.
Agreed. Note that you've over-simplified things in terms of what systems
do with pass by invisible reference structures -- some ABIs have the copy
made by the callee (which allows the callee to avoid the copy if it never
modifies the structure).
> However, even in a first implementation, I wish to treat BPs
> specially: they should always be passed and returned by value in
> registers whenever possible. When passing, they would be logically
> treated as three consecutive simple pointer args. When returning,
> they would be placed in three consecutive return-value registers. On
> ix86, that would be %eax, %edx, %ecx. On PowerPC, that would be r3,
> r4, r5. Even though MIPS ABI has only two value-return registers, we
> can use `a0' as a third, since this entire BP-passing scheme goes
> beyond the ABI.
Conceptually it's like the structure passing conventions for PA64 and
I believe the latest sparc ABIs -- you conceptually lay out an argument
list in memory, then copy as much of it as possible into a series of
registers (again that's the conceptual model -- that's not actually how
its done).
> It seems conceptually simple enough to implement: instead of DECL_RTL
> being a MEM for the entire struct, make it some form of table (vector
> or list or whatever) that holds an RTX for each member of the struct.
> Expanding a COMPONENT_REF will do a lookup to find the proper RTX.
> The table can be sparse, omitting RTXes for members that are unused.
> If the struct's address is taken, we toss the table and revert to the
> traditional MEM. Taking the address of a member should force only
> that member into memory, not the entire struct.
Seems generally reasonable, though you've got to fight the problem of
dumping stuff to memory *after* you've already creates its DECL_RTL. In
a number of ways it's similar to the ADDRESSOF problem where we have these
magic tidbits lying around for a while then after various optimizations we
have to convert them to sensible RTL.
jeff