On Tue, 6 Aug 2013, Gabriel Dos Reis wrote:

> On Tue, Aug 6, 2013 at 1:46 PM, Nathan Sidwell <nat...@acm.org> wrote:
> > Hi,
> > i386elf.h defines:
> >
> > /* The ELF ABI for the i386 says that records and unions are returned
> >    in memory.  */
> >
> > #define SUBTARGET_RETURN_IN_MEMORY(TYPE, FNTYPE) \
> >         (TYPE_MODE (TYPE) == BLKmode \
> >          || (VECTOR_MODE_P (TYPE_MODE (TYPE)) && int_size_in_bytes (TYPE) ==
> > 8))
> >
> > and as such differs from the regular i86 return mechanism.  Notice that the
> > comment doesn't match the code:
> > *) some structs/unions are non BLKmode
> > *) some vectors can be BLKmode, some might not be -- the vector mode check
> > appears to be an attempt to catch DImode vectors.
> >
> > Basing your ABI on the internal modes used by the compiler is not, IMHO, a
> > sensible design choice.
> >
> > This code doesn't appear at first glance to cope with transparent_union.  In
> > fact it looks pretty bitrotted.
> >
> > Is it best just to junk the different behaviour at this point?
> 
> Yes and yes :-)

 This piece was introduced along i386elf.h itself at r28057 (1999-07-11) 
as:

#define RETURN_IN_MEMORY(TYPE) \
  (TYPE_MODE (TYPE) == BLKmode)

while the corresponding i386.h piece was:

#define RETURN_IN_MEMORY(TYPE) \
  ((TYPE_MODE (TYPE) == BLKmode) || int_size_in_bytes (TYPE) > 12)

AFAICT at that time for the i386 target GCC only supported integer and x87 
data types.  The largest native (hardware) data type therefore was the x87 
80-bit extended represented in C as a 12-byte `long double' type.  For 
this and narrower types the two macros produce the same result.  Also at 
that time IIUC all structs/unions were BLKmode.

 So the difference between the two macros only applied to complex types.
The former would only put `float complex' data in registers (EDX:EAX) -- 
because that type fits in 8 bytes -- and any other results in memory.  The 
latter however wanted to put all complex data in registers, including 
`double complex' (16 bytes) and `long double complex' (24 bytes).

 As observed by Nathan in:

http://gcc.gnu.org/ml/gcc-patches/2013-08/msg00373.html

this can't possibly work, as i386 only makes 3 GPRs possibly available 
(defined as call-clobbered) for results: EAX, EDX and ECX.

 Jeff, given the above -- do you happen to remember what made you make the 
i386/ELF target different from the base i386 target?  Did I miss anything 
in the consideration above?  The decision looks like has been deliberate, 
the i386.h default would normally apply (as i386elf.h included it at the 
beginning), but the macro was explicitly undefined and then defined as 
above.

 Of course even the decision made by the base i386 target to put `float 
complex' data in GPRs seems odd to me -- that's awkward and costly to 
handle as there's no way to pass such data between FPRs and GPRs without 
going through memory (so what's the point not to just leave it there?).  
And then this data is obviously useless in GPRs as it has to be put back 
to FPRs by the caller by the same long route if any further arithmetic is 
required.  If in registers at all, I would expect complex results to be 
returned in ST(1):ST(0) -- that would make them accessible right away and 
the ABI consistent with real results returned in ST(0).

 Then, as further evolution, with the addition of MMX and SSE support at 
r34721 (2000-06-26) both macros were changed, to:

#define RETURN_IN_MEMORY(TYPE) \
  (TYPE_MODE (TYPE) == BLKmode \
   || (VECTOR_MODE_P (TYPE_MODE (TYPE)) && int_size_in_bytes (TYPE) == 8))

and:

#define RETURN_IN_MEMORY(TYPE)                                                \
  ((TYPE_MODE (TYPE) == BLKmode)                                              \
   || (VECTOR_MODE_P (TYPE_MODE (TYPE)) && int_size_in_bytes (TYPE) == 8)     \
   || (int_size_in_bytes (TYPE) > 12 && TYPE_MODE (TYPE) != TImode            \
       && ! VECTOR_MODE_P (TYPE_MODE (TYPE))))

respectively, which IIUC made MMX data returned in memory and SSE data in 
registers -- in both cases.

 Bernd, if you still remember: am I missing anything here?  Especially the 
TImode piece is unobvious to me -- why would it matter for MMX/SSE?  
Neither supports 128-bit integers.

 From this point onwards no further changes were made to the version of 
RETURN_IN_MEMORY in i386elf.h.

 The version in i386.h was updated with r39693 (2001-02-14):

#define RETURN_IN_MEMORY(TYPE)                                          \
  ((TYPE_MODE (TYPE) == BLKmode)                                        \
   || (VECTOR_MODE_P (TYPE_MODE (TYPE)) && int_size_in_bytes (TYPE) == 8)\
   || (int_size_in_bytes (TYPE) > 12 && TYPE_MODE (TYPE) != TImode      \
       && TYPE_MODE (TYPE) != TFmode && ! VECTOR_MODE_P (TYPE_MODE (TYPE))))

and then in r45726 (2001-09-21) factored out to ix86_return_in_memory:

#define RETURN_IN_MEMORY(TYPE)                                          \
  ix86_return_in_memory (TYPE)

-- which eventually evolved to its current form.

 My conclusion therefore is i386/ELF was not maintained, as far as the 
return convention is concerned, beyond r34721 and it looks to me like it 
should have been converted with r45726 to make use of 
ix86_return_in_memory just like generic i386, perhaps with a special 
exception for complex types (although as I noted above, this exception was 
probably a mistake from the beginning).

 Any thoughts?

  Maciej

Reply via email to