Generating Intrinsic Functions (/Oi)

In place of some normal function calls, the C/C++ compiler can insert “intrinsic functions,” which operate more quickly. Every time a function is called, a set of instructions must be executed to store parameters and to create space for local variables. When the function returns, more code must be executed to release space used by local variables and parameters and to return values to the calling routine. These instructions take time to execute. In the context of an average-sized function, the additional code is minimal, but if the function is only a line or two, the additional code can comprise almost half of the function's compiled code.

One way to avoid this type of code expansion is to avoid such short functions, especially in often-used sections of code where speed is critical. But many library functions contain only a line or two of code. The compiler provides two forms of certain library functions. One form is a standard C function, which requires the overhead of a function call. The other form is a set of instructions that performs the same action as the function without issuing a function call. This second form is called an intrinsic function. Intrinsic functions are always faster than their function-call equivalents and can provide significant optimizations at the object-code level.

For example, the function strcpy might be written as follows:

int strcpy(char * dest, char * source)

{

while( *dest++ = *source++ );

}

The compiler contains an intrinsic form of strcpy. If you instruct the compiler to generate intrinsic functions, any call to strcpy will be replaced with this intrinsic form.

Note:

While the preceding example is written in C for clarity, most of the library functions use assembly language to take full advantage of the 80x86 instruction set. Intrinsic functions are not simply library functions defined as macros.

Compiling with the /Oi option causes the compiler to use the intrinsic forms of the following functions:

abs_disable_enable_inp_inpwlabs_lrotl_lrotrmemcmpmemcpymemset_outp_outpw_rotl_rotrstrcatstrcmpstrcpystrlen_strset

While the following floating-point functions do not have true intrinsic forms, they do have versions that pass arguments directly to the floating-point chip instead of pushing them on the normal argument stack:

acosasinatanatan2ceilcoscoshexpfloorfmodloglog10powsinsinhsqrttantanh_acosl_asinl_atanl_atan2l_ceill_cosl_coshl_expl_floorl_fmodl_logl_log10l_powl_sinl_sinhl_sqrtl_tanl_tanhl

Warning!:

The compiler performs optimizations assuming math intrinsics have no side effects. This assumption is true except if you have written your own _matherr function and that function alters global variables. If you have written a _matherr function to handle floating-point errors, and your function has side effects, use the function pragma to instruct the compiler not to generate intrinsic code for math functions.

If you want the compiler to generate intrinsic functions for only a subset of the functions listed above, use the intrinsic pragma rather than the /Oi option. The intrinsic pragma has the following format:

#pragma intrinsic( function1, ... )

If you want to have intrinsic functions generated for most of the functions above and function calls for only a few, compile with the /Oi option and force function use with the function pragma. The function pragma has the following format:

#pragma function( function1, ...)

The following code illustrates the use of the intrinsic pragma:

#pragma intrinsic(abs)

void main( void )

{

int i, j;

i = big_routine_1();

j = abs( i );

big_routine_2( j );

}

Generating intrinsic functions for this program causes the call to abs to be replaced with assembly-language code that takes the absolute value of a number. The program will execute more quickly because the function-calling overhead is no longer required when abs is called.

In the previous example, the overall speed increase is small because there is only a single call to abs. In the following example, where the call to abs is in a loop and there are many calls, you can save a significant amount of execution time by generating intrinsic functions.

#pragma intrinsic( abs )

void main( void )

{

int i, j, x;

for( j = 0; j < 1000; j++ )

{

for( i = 0; i < 1000; i++ )

{

x += abs( i - j );

}

}

printf( “The value of x is %d\n”, x );

}

The following is a list of restrictions on using the intrinsic forms of function calls:

Do not use the intrinsic forms of the floating-point math functions with the alternate math libraries (mLIBCAy.LIB).

The /Oi option is not available if you use the /Oq option (p-code generation).

If you use the /Ox (maximum optimization) option, you are enabling the /Oi (generate intrinsic functions) option. Be careful that your use of /Ox does not conflict with the points listed previously.