function calls

Tim Olson tim at nucleus.amd.com
Tue Mar 20 01:37:54 AEST 1990


In article <14273 at lambda.UUCP> jlg at lambda.UUCP (Jim Giles) writes:
| From article <29509 at amdcad.AMD.COM>, by tim at nucleus.amd.com (Tim Olson):
| > [...]
| > If you partition your registers into a set that is live across a
| > function call and a set that is killed, then leaf routines can run
| > entirely out of the later set, not having to save any registers.  For
| > example, in the Am29000 calling-convention, a function can allocate up
| > to 126 local registers which are saved across function calls and
| > also has use of 24 "temporary" registers which are not.  Most leaf
| > routines can run entirely out of these 24 temps.  The entire overhead
| > is simply a call instruction and a return instruction (2 cycles if the
| > delay slots are filled).
| 
| It seems to me that if a procedure is so small that it can only find
| use for 24 (or fewer) registers, then it is small enough to be a real
| good candidate for inlining.  Clearly, _any_ procedure can be written
| only _use_ 24 registers (there were some machines in the past with only
| _one_ register - the were completely functional).  However, most procedures
| of any size can benefit from quite a few more registers than 24.

It might be true that scientific routines written in FORTRAN may have
this many live, non-overlapping variables to keep in registers, but I
don't believe this is true in general.  Statistics from a large
collection of programs and library routines (a mix of general and
scientific applications written in C) show that of 782 functions (620
of which were non-leaf functions), an average of 6.5 registers per
function were live across function calls.

| Similarly, any 'caller' routine that can afford to leave 24 registers
| unused is fairly small as well.  For efficiency, all 'live' values
| should be kept in registers if at all possible.  The problem is that
| any large program (and some small ones) have quite a large number of
| 'live' values.  Procedures that manupulate arrays may have whole
| arrays (or array sections) that are 'live'.   If there's _room_ in
| the register set for all these values, that's where they should be
| kept.

Yes, this is true.  However, unless the array manipulation is quite
simple, it becomes tricky to use registers for them (the stats quoted
above were for scalar variables only).

| The fact is that this kind of 'temp' register idea only _appears_
| to save time.  You probably actually lose performance by forcing
| many of your 'live' values to memory when they needn't have been.

No live values were forced to memory (at least not ones in the active
function).  The Am29000 stack cache tries to keep live variables from
all functions in the register file as well as the variables of the
current function.  If the register file becomes full, live variables
from older functions are spilled to memory, then filled as they become
active again.

	-- Tim Olson
	Advanced Micro Devices
	(tim at amd.com)



More information about the Comp.lang.c mailing list