function calls

Tim Olson tim at nucleus.amd.com
Sat Mar 24 01:27:42 AEST 1990


In article <14285 at lambda.UUCP> jlg at lambda.UUCP (Jim Giles) writes:
| From article <29585 at amdcad.AMD.COM>, by tim at nucleus.amd.com (Tim Olson):
| > [...]
| > The compiler that I used to collect the stats will keep all live
| > scalars in the register file, [...]                    [^^^]
| 
| I don't believe a word of it.  The word I don't believe is 'all'.
| _ANY_ scalar that is visible in the local scope and has a value
| which might still be used by the program at some future point is 'live'.
| (The same obviously applies to non-scalar values.)  That is the definition
| of 'live'.

Sorry -- I should have clarified that it keeps all live scalar
variables *that don't have potential aliasing problems* in the
register file.  Since global variables are visible to other functions,
they have the potential for having their address taken in some other
compilation unit (remember, we are talking about C code), and thus
cannot be kept in registers -- unless "universal" register allocation
and optimization is performed.

| What you really mean is that the compiler breaks code into
| 'basic blocks' and keeps all active values from _that_ block in registers.
| The use of 'basic blocks' and the lack of global dataflow analysis is
| confusing you into thinking that only a few values are 'live' at a given
| point.

No, the compiler is performing register allocation on an entire
function, not on a basic block level.  It is performing "global"
dataflow analysis (meaning on a per-function basis), but not
"universal" dataflow analysis (on the entire program, including all
other compilation units).

| Also, it is considerable mistake not to regard non-scalar values
| as important.

I never said they weren't important -- it is just that it is very hard
(sometimes impossible) to operate on structures and arrays that are
kept entirely in registers (runtime indexing, etc.).  If you mean that
*scalar elements* of an array that are used often should be kept in
the register file, then I agree, and we do that.

| The bottom line is that registers are an important resource in any machine.
| They are often more that 10 times faster than memory to reference.  Your
| analysis indicates that your code (whether the compiler is responsible
| or not) is using this resource to only a small fraction of its potential.
| But instead of complaining, you are acting like it is a desireable way
| for the code to behave.

No, I don't claim it is "desireable", just that a lot of
general-purpose C code tends to have a large number of small to
medium-sized functions which use < 20 local scalars.

| Ok, now I have statistics.  I just did a quick survey of some expertly
| crafted C code that I have source code to (it's actually part of the
| X11 window package).  This is only a small program (it's xlock for those
| interested in checking).  Still, there are over 50 scalar variables
| declared global to the utility - these are _ALWAYS_ 'live'.
	   ^^^^^^

OK -- now I see where you are getting your numbers and where we are
differing.  The stats I collected were for local ("automatic")
scalars, because global scalars can have aliasing problems unless we
perform "universal" dataflow analysis.  I agree that if this were
done, the number of variables live across a function call increase
dramatically.

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



More information about the Comp.lang.c mailing list