Usage of ANSI-C |const| in X11 code...

Ian Romanick idr at us.ibm.com
Fri Mar 25 18:40:28 PST 2005


Roland Mainz wrote:
> Adam Jackson wrote:
>>On Friday 25 March 2005 16:12, Roland Mainz wrote:
>>
>>>AFAIK on some platforms (SPARC comes in mind) it makes a huge difference
>>>as values are passed in registers (unless all registers are used up) and
>>>not via the stack (and no stack version is provided).
>>
>>Yes, this is true on x86 too.  However the register keyword has nothing to do
>>with function calling conventions.
> 
> AFAIK it depends... some compilers may just modify the calling
> conventions to fit their needs if they can control all the callers, too
> (for example when the compiler has a global view about the whole
> application in the Sun Workshop XIPO case or for |static| functions).

I have some experience with this on GCC and libGL.  Basically, GCC will 
inline, use register parameters, and do other tricks (e.g., use jumps 
instead of call / ret pairs) on functions that are static to a file and 
that are never referenced via a pointer.

In addition, there are ways to force register based parameter passing on 
x86.  Using the "register" keyword is *NOT* one of them.  The way that I 
have used most often is the fastcall attribute.  The regparm can also be 
used, but I'm less familiar with it.  Basically, if a function is 
declared as:

__attribute__((fastcall)) extern void foo( int arg1, int arg2,
     float arg3, int arg4 );

the first 3 parameters will be passed in registers, and the remaining 
parameters will be passed on the stack.  This is used extensively in the 
autogenerated code for GLX protocol.

The way that I have done this is by creating a macro called FASTCALL 
based on some GCC pre-defines:

#if defined(__i386__) && defined(__GCC__)
#  define FASTCALL __attribute__((fastcall))
#else
#  define FASTCALL
#endif

x86 is the only common arch that I know of that doesn't use register 
parameter passing by default, so I didn't bother to try and extend it 
for anything else.  The other down side is that not all GCC builds seem 
to support the fastcall attribute even on x86.  The result is a warning 
that the attribute is ignored.  Since this attribute is only used on 
functions that are internal, I didn't worry about ABI issues (i.e., the 
function built with fastcall supported, but the caller built without).

I use similar tricks for the "pure", "alias", "visibility", and 
"noinline" attributes, as well as a couple GCC __builtin_ pseudo-functions.

'info gcc "C Extensions" "Function Attributes"' has some more information.

>>>>If we find performance-critical code where inlining makes a difference
>>>>for a given compiler, we should handle that case-by-case, because
>>>>heuristics differ and what's fast in gcc may be slow in sun c.
>>>
>>>My point with using |inline| was more to replace some of the very ugly
>>>#define macros with |inline| functions (|static inline| to be exactly)
>>>to give the compiler better ways for type checking, the optimizer a way
>>>to analyse (e.g. profiling) the code correctly (I am looking here at Sun
>>>Workshop's XIPO option which allows the optimizer to operate application
>>>wide in one step (e.g. the optimizer can inline&&optimize over all
>>>source files in one step (which gives nice performance boosts when this
>>>step is combined with profile-feedback))) and make the code more
>>>readable, too.
>>
>>That sounds reasonable.
> 
> OK... how should the usage of |inline| be handled ? We need 1) a way to
> detect support for |inline| and 2) a convention for what should be done
> if |inline| isn't supported (just doing a |#define inline| isn't
> possible as this may cause trouble with system includes (or better:
> compiler-specific includes) so we either need something like |#ifdef
> SUPPORTS_INLINE\n#define _Xstaticinline static inline\n#else\n#define
> _Xinline static\n#endif| or a different way to guard this stuff... any
> comments/suggestions/ideas ?

For macros that wrap funky keywords and the like, I usually make the 
macro version all upper case.  So, I would suggest using INLINE.  The 
functions would look like:

static INLINE int foo( int * x, float * y, int z )
{
     ...
}

Would there ever be a case where we would want "static inline" when 
inline is supported, but non-static if inline isn't supported?



More information about the xorg mailing list