Liste des Groupes | Revenir à c arch |
On Mon, 6 Jan 2025 15:32:04 +0000, Anton Ertl wrote:
David Brown <david.brown@hesbynett.no> writes:But the ABI only allows returning a single 32-bit value in R0, or a
scalar 64-bit value in R0:R1. If a function returns a non-scalar that
is larger than 32-bit, the caller has to allocate space on the stack for
the return type and pass a pointer to that space in R0.
>
To my mind, this is massively inefficient, especially when using structs
that are made up of two 32-bit parts.
>
For /some/ circumstances it is certainly true that passing by reference (or by pointer, or by hidden pointer on the stack) is more efficient, especially for larger aggregates. For others - especially smaller aggregates - using registers is vastly more efficient.>For VERY MANY circumstances passing a struct by address is more
I wonder, though, how things look for
>
mystruct = foo(&mystruct);
>
Does PCC perform the return stores to mystruct only after performing
all other memory accesses in foo? Probably yes, anything else would
complicate the compiler. In that case the caller could pass &mystruct
for the return value (a slight complication). But is that restriction
reflected in the calling convention?
efficient than passing it by value, AND especially when the
compiler does not optimize heavily.
I already know when it is best to pass a struct via a pointer, and when it is best to pass it as a struct value. (The 32-bit ARM calling convention happily uses registers to pass structs by value, using up to 4 registers. It's the return via registers that is missing.) I also know when it is best for a struct return to be via an address or in registers - but C has no way to let me choose that.Struct returns were (and AFAIK still are, many decades afterIn addition, the programmer has the choice of changing into pointer
they were added to C) a relatively rarely used feature, so Johnson
(PCC's author) probably did not want to waste a lot of effort on
making it more efficient.
form (&struct) from value form (struct) which is what we learned
was better style way back then.
--------------------------The trouble with that kind of thing is that people write different kinds of code. The balance that works best for - say - PC desktop application programming is not necessarily the best for small-systems embedded programming. And the balance that works best for C is not necessarily the best for C++, or Rust, or D, or OCaml or any other language.
Compiler people were telling us that more callee saved registers wouldI also think code would be a bit more efficient if there more registers>
available for parameter passing and as scratch registers - perhaps 6
would make more sense.
There is a tendency towards passing more parameters in registers in
more recent calling conventions. IA-32 (and IIRC VAX) passes none,
MIPS uses 4 integer registers (for either integer or FP parameters),
Alpha uses 6 integer and 6 FP registers, AMD64's System V ABI 6
integer and 8 FP registers, ARM A64 has 8 integer and 8 FP registers,
RISC-V has 8 integer and 8 FP registers. Not sure why they were so
reluctant to use more registers earlier.
be higher performing than more argument registers. It did not turn out
to be that way.
Oh and BTW, lack of argument registers leads to an increasedCertainly a way out of this is to look to link-time optimisation and more inline code. But that leads to a lot of additional issues.
desire for the linker to perform inline folding. ...
Les messages affichés proviennent d'usenet.