[comp.lang.c] a reasonable approach to inlining

ziel@spot.Colorado.EDU (ZIEL FRED ADAM) (06/17/88)

One of the things I think Microsoft did right with C 5.0 was add "intrinsic"
functions.  These are standard library functions such as movmem, strcmp, strcpy,
inp, outp, etc. that are inlined.  The instrinisic code generation
can be turned on and off individually for each function using a #pragma.
This came in handy when their intrinsic inp and outp didn't work on version
5.0 of the compiler since I could keep the inlining for the functions I
wanted, but turn it off for those two.  They also have #pragma's to control
the optimizations which is handy since it allows you to disable loop optimation
around a certain loop if that is necessary (ie. optimized null delay loops
don't serve their purpose if they are optimized away [yes, I know there are
better ways than delay loops... it's an example]).  Are these uses of 
#pragma common ones?  I though they were pretty handy. 

----------------------------------------------------------------------
Fred Ziel, Colorado Center for Astrodynamics Reserach, CU-Boulder 
uucp:   ..!{nbires,ames!ncar}!boulder!ziel  domain: ziel@spot.colorado.edu
disclaimer.h (line 10): syntax error.

chris@mimsy.UUCP (Chris Torek) (06/17/88)

In article <6667@sigi.Colorado.EDU> ziel@spot.Colorado.EDU (ZIEL FRED ADAM)
writes:
>... Microsoft ... C 5.0 ... "intrinsic" functions.  These are standard
>library functions such as movmem, strcmp, strcpy, inp, outp, etc. that
>are inlined.  The instrinisic code generation can be turned on and off
>individually for each function using a #pragma.

The dpANS provides for inline generation in a different way:  For
instance,

	#include <math.h>
	...
		double low; ... low = floor(arg);

might generate floor inline, while

	#include <math.h>
	#undef floor
	...
		double low; ... low = floor(arg);

will refer to a library routine.

Note that this makes it difficult to temporarily refer to the library
version; with #pragma one can presumably turn inlining back on later.
I do not know whether the dpANS allows a second

	#include <math.h>

to turn floor back into an inline.

>... They also have #pragma's to control the optimizations ...  ie.
>optimized null delay loops don't serve their purpose if they are
>optimized away ...

This, incidentally, is yet another reason that either pragmas should
not be like `preprocessor' controls, or that `#define' macros should be
allowed to expand to such controls.  A delay macro like

	#define	DELAY(n) {int delay_tmp = (n); while (delay_tmp--) /*void*/;}

should clearly disable optimisation, yet if this is to be done with
`#pragma', we need something like

	#define DELAY(n) { \
		int delay_tmp = (n); \
		#pragma optimisation: push state \
		#pragma optimisation: none \
		while (delay_tmp--) /*void*/; \
		#pragma optimisation: pop state \
	}

but by all the rules, these `#pragma's are in the wrong place.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

breck@aimt.UUCP (Robert Breckinridge Beatie) (06/17/88)

In article <11996@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> The dpANS provides for inline generation in a different way:  For
> instance,
> 	#include <math.h>
> 	...
> 		double low; ... low = floor(arg);
> might generate floor inline, while
> 	#include <math.h>
> 	#undef floor
> 	...
> 		double low; ... low = floor(arg);
> will refer to a library routine.
> 
> Note that this makes it difficult to temporarily refer to the library
> version; with #pragma one can presumably turn inlining back on later.
> I do not know whether the dpANS allows a second
> 
> 	#include <math.h>
> 
> to turn floor back into an inline.

It struck me that since preprocessing and translation are supposed to be
"logically successive phases" it might not be necessary to re-include <math.h>
So, the question I'm asking is would it work (portably) to do something like:

	#include <math.h>
	#define TEMP floor
	#undef floor		/* should turn off inlining for floor */
	...
		double low; ... low = floor(arg);
	#define floor TEMP	/* hopefully turns inlining back on */
	#undef TEMP

???

This seems ugly as all get out, but I can't think of any reason that it
wouldn't work.  Of course I'm pretty ignorant of the details of the dpANS,
but then that's why I'm asking the question.

So, given that a compiler replaces calls to floor() with inline code, will
that work?
-- 
Breck Beatie	    				(415)856-8649
{uunet,ames!coherent}!aimt!breck
"Sloppy as hell Little Father.  You've embarassed me no end."

gwyn@brl-smoke.ARPA (Doug Gwyn ) (06/18/88)

In article <11996@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>I do not know whether the dpANS allows a second
>	#include <math.h>
>to turn floor back into an inline.

I think it is allowed, but not required.  However, I suspect that in
most implementations only the first inclusion of a standard header
will have any effect.

mouse@mcgill-vision.UUCP (der Mouse) (06/25/88)

In article <1087@aimt.UUCP>, breck@aimt.UUCP (Robert Breckinridge Beatie) writes:
> In article <11996@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
>> [about inlining functions and how it can be suppressed]
>> Note that this makes it difficult to temporarily refer to the
>> library version; [...]  I do not know whether the dpANS allows a
>> second  #include <math.h>  to turn floor back into an inline.
> So, the question I'm asking is would it work (portably) to do
> something like:
> 	#include <math.h>
> 	#define TEMP floor
> 	#undef floor		/* should turn off inlining for floor */
> 	...
> 		double low; ... low = floor(arg);
> 	#define floor TEMP	/* hopefully turns inlining back on */
> 	#undef TEMP

No, this wouldn't work....  Let's see what happens to

#include <math.h>
#define TEMP floor
#undef floor
floor(foo);
#define floor TEMP
#undef TEMP
floor(foo);

in the preprocessor.  (I'm concerned with just the preprocessor here,
so I didn't bother putting the above in a function body.)

Let's see what happens to the first floor(foo);.  First it gets
tokenized:

	floor ( foo ) ;

This is scanned for macros.  None are found, so we get those five
tokens in the output stream of the preprocessor.

Now, the second one:

	floor ( foo ) ;

Aha, floor is defined.  What's it defined as?  TEMP.

	TEMP ( foo ) ;

There are no further defined names there (we #undefined TEMP).  So it
now turns into a function call to TEMP, whatever that is.

> This seems ugly as all get out, but I can't think of any reason that
> it wouldn't work.

You seem to be expecting the preprocessor to behave a bit differently
from the way it really does.  When a macro is defined in terms of
another macro (or macros), the expansion is not scanned for other
definitions at the time of the #define, but rather after expanding the
macro.  For example, the following produces "foo", not "bar":

#define XXX bar
#define YYY XXX
#define XXX foo
YYY

As far as I know, there is no way to force the preprocessor to expand
macros in the replacement text of a definition at the time the #define
is done rather than at the time the macro is used.  This might be a
useful feature; does it exist anywhere at present?

					der Mouse

			uucp: mouse@mcgill-vision.uucp
			arpa: mouse@larry.mcrcim.mcgill.edu