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]

Re: [IRIX 6/Ultrix V4] Non-MIPS-ABI conformant passing of small structures


In article <14193.11353.86535.794466@xayide.techfak.uni-bielefeld.de> you write:
>* Because someone thought it's inefficient, mips.c (function_arg) decided
>  not to follow the MIPS ABI in left-aligning small structures.

Not quite.  What happened first is that a gcc specific 64-bit ABI was created,
which is now being called o64 for convenience.  This ABI did not left align
small structures because of an efficiency problem.  Later, SGI created 64 bit
ABIs called n32 and n64 which continued to require left-aligning like o32.
These new ABIs were never completely implemented.

>  I simply
>  removed the test for !TARGET_64BIT since this convention is valid both
>  for the o32 and n32/n64 ABIs, as described in 

This changes the o64 ABI which is unnecessary and undesirable.  I'd suggest
changing the ! TARGET_64BIT to mips_abi != ABI_O64 which matches the original
intent.  This will likely require an additional va-mips.h change, but we can
worry about that later.

This change doesn't completely fix the ABI compliance problem though.  It works
only for structures smaller than 8 bytes.  We still have the problem that
structures greater than 8 bytes but less than 16 bytes are still handled
incorrectly.  The extra bytes in the second register need to be left-aligned,
but are not.

The efficiency problem is that while the SGI compiler emits a single 8 byte
load instruction for a 4 byte structure (thereby giving left-alignment on
a big-endian target), gcc emits a 4 byte load followed by a shift.  Ideally,
gcc should emit a single 8 byte load like the SGI compiler does.  The 8<X<16
byte case naturally follows from this, because then it is just 2 8-byte loads.

Fixing the general case, which means handling all structure sizes, without
loss of efficiency, is a very hard problem, because this will require
complicated changes to the machine-independent support for loading/storing
function arguments.  Attempts to change this code will likely introduce bugs
affecting lots of ports, and it will be hard to find and fix all of these
bugs.

However, relatively recently, we've introduced a second way to load/store
function arguments, which allows the machine dependent files to exercise some
control over how functions arguments are loaded/stored.  This is the support
that allows function_arg to return a PARALLEL.  These PARALLELs are then
handled by emit_group_load/emit_group_store in expr.c.  Originally this
handled some funny cases where arguments needed to split across two
non-adjacent locations.  But thanks to the 64-bit sparc ABI, which had a
problem very much like this mips n32/n64 problem, the PARALLEL support can
now also handle loading of structures which need to be big-endian left aligned.

I'd suggest forgetting about the archaic and ugly left-shift structure code
in the mips function_arg function, and instead fix the problem by making
function_arg return a PARALLEL for the n32/n64 ABIs when the argument is
a structure which is not a multiple of 8 bytes, and will be passed entirely
in registers.  I think this is a more elegant solution, and it does a much
better job of fixing the general problem.  We probably need a similar change
for mips_function_value to handle structure return values.  We still have
an efficiency problem, but at least it is now in the emit_group_load/store
functions, which are easier to change than the general argument handling
code in calls.c/function.c.

Jim


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