[fpc-devel]default calling convention change for i386
Anton Tichawa
anton.tichawa at chello.at
Wed Dec 24 16:36:54 CET 2003
Hello!
On Wednesday 24 December 2003 13:00, Ingmar Tulva wrote:
>
> Anyway, has someone actually analyzed how benefitial register calling
> convention is? Sure it provides huge speed boost in case of a function
> which adds two arguments together and returns the result - or is it so
> sure? In fact, I imagine that in most cases, register convention will
> eventually be detrimental to both speed and code size.
>
> Again, no complain intended, just curiousity.
>
I'm not a developper of free-pascal, so the following statements are just
general considerations.
To me, register convention is a great step forward, concerning the economic
usage of available resources.
Register convention saves opcode space in the called function, because within
the instruction opcode, registers are encoded with small bit fields, whereas
offsets into a stack frame are encoded as (8-, 16-, or 32-bit) words, unless
the processor supports something like short offsets. Actually, I don't know
if the i386 does support such short offsets. AFAIK, the 68000 does not.
Every register parameter also saves at least two memory (stack) accesses,
which are considerably slower compared to register accesses and increase bus
use.
When writing low-level functions in 680x0 assembler, I always pass parameters
in registers (there are 15 of them, which is quite a lot). In an embedded
system, I sometimes even use "global" register variables, e. g. register D7
contains, throughout the whole program, the current user ID.
A bit off-topic: I also return boolean result in a processor flag, to allow
fast testing:
pascal:
begin
if my_boolean_function then begin
bla
assembler
jsr my_boolean_function
bcs.s yes
..
yes: bla
Implementations I know of, pass boolean result in D0, which is slower, but
still faster compared to stack parameters.
In 180 degree contradiction to your opinion, I think that register convention
will, in most cases, save both memory and execution time :)
As an example, consider the call
function main;
var
a: integer;
b: integer;
begin
my_function(a, b);
end;
With conventional calling:
move a, -(a7) // 2 memory accesses
move b, -(a7) // 2 memory accesses
jsr my_function
WIth register calling:
move a, d0 // 1 memory access
move b, d1 // 1 memory access
jsr my_function
This example still does not include the benefits within procedure my_function,
namely the saving of instruction extension words with stack offsets. In that
case, 2 memory accesses (to the instruction extension word and to the stack
data) are saved by register convention.
A further benefit would result from optimization between the registers passing
parameters to my_function, and the registers used within function main for
variables a and b, by allocating identical registers, thus removing
instructions of the form "move d5, d5". That's an optimization technique easy
in assembler, but difficult for a compiler, especially when maintaining
register allocation through serveral levels of function calls.
If anyone does some performance testing, comparing the two conventions, please
post it to the list.
Anton.
More information about the fpc-devel
mailing list