Potential optimisation?
B. Banerjee
bbanerje at sjuvax.UUCP
Sat Jan 19 16:21:37 AEST 1985
Hi,
Please don't flame me, despite what my .signature entry may say. This
is in the spirit of honest enquiry. I don't know whether the following
is feasible in the presence of signals and the like.
I was thinking of the possible ways that C could be sped up, in a
general fashion. Part of the philosophy of using procedural languages
such as C, is that the incentive is present to break up the program
into small manageable functions. Much of this incentive is lost if the
function call is overly expensive.
1) The current process of passing parameters on the stack has many
advantages. Primary among these are the capabilities of declaring
routines that take a variable number of arguments (*Yes*, they are
often necessary, and even clean). Also, a consistent calling interface
is desirable when linking in separately compiled, or assembly language
routines. Unfortunately, this adds a great deal of unnecessary
overhead.
One way to handle this would be to handle calls to 'static' functions
differently, based on observed usage in the rest of the file (NOTE:
this probably would require multiple passes). Parameterless static
functions could be called via a 'jsr' or equivalent. Functions with
fewer than 'n' constant arguments could have their arguments passed in
registers. Static functions whose usage indicated a VARARGS usage
would have the parameters passed in the usual fashion. Static
functions which are only referenced once or twice could be expanded
inline. Now, so far there is nothing new here. However....
I took a look at a lot of C code on my (4.2 BSD) system. An informal
guess would be that over 50% of the functions in the source files could
be declared as 'static'. Now, let us say that we have another keyword
'exported' which is used to label those functions which are called from
other source files. All functions which were *not* declared to be
*exported* would be considered static by default. This would allow the
efficient generation of code. It would also be easier to read code
that used this, as one would not have to sit down with a cross
reference listing. Furthermore, register allocation could be done on
an inter-functional basis. Lastly, the code could be portable through
the use of ...
# define exported /* foobar */
in a header file, effectively stripping them in the case where they
were not understood.
2) In a UNIX C compiler (to the best of my knowledge) two assembly
procedures CSV and CRET are used to save and restore the registers in
the *called* procedure. I fail to see why this is desirable. The
*calling* procedure has full knowledge of which registers are being
used and can save them itself. This may not result in savings, but I
don't see where it can result in a performance degradation.
3) Automatic data definitions are always allocated space on the
stack. This is fine in the presence of recursive functions. However,
in practice, recursive functions are not very heavily used. Some means
of data flow analysis might allow the allocation of automatic data
statically at compile time, with each datum at a constant offset from
the start of the object file. The data flow analysis could enable the
re-use of space. This would allow processes to take up less space
while running, as the maximum stack size would be known at compile
time. Of course, recursive functions would still have their local data
allocated on the stack.
Well, what do you think. I would appreciate some feedback on this.
Please reply by mail. If the responses warrant it, I will summarize to
this group.
Regards,
--
Binayak Banerjee
{allegra | astrovax | bpa | burdvax}!sjuvax!bbanerje
P.S.
Send Flames, I love mail.
More information about the Comp.lang.c
mailing list