Xref: utzoo comp.lang.c:27178 comp.lang.misc:4631 Path: utzoo!utgpu!news-server.csri.toronto.edu!clyde.concordia.ca!uunet!mailrus!ames!amdcad!nucleus!tim From: tim@nucleus.amd.com (Tim Olson) Newsgroups: comp.lang.c,comp.lang.misc Subject: Re: function calls Message-ID: <29596@amdcad.AMD.COM> Date: 23 Mar 90 15:27:42 GMT References: <29585@amdcad.AMD.COM> <14285@lambda.UUCP> Sender: news@amdcad.AMD.COM Reply-To: tim@amd.com (Tim Olson) Organization: Advanced Micro Devices, Inc., Austin, Texas Lines: 69 Summary: Expires: Sender: Followup-To: In article <14285@lambda.UUCP> jlg@lambda.UUCP (Jim Giles) writes: | From article <29585@amdcad.AMD.COM>, by tim@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@amd.com)