HPlogo HP C/HP-UX Programmer's Guide: Workstations and Servers > Chapter 4 Optimizing HP C Programs

Optimizer Pragmas

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Index

Pragmas give you the ability to:

  • Control compilation in finer detail than what is allowed by command line options.

  • Give information about the program to the compiler.

Pragmas cannot cross line boundaries and the word pragma must be in lowercase letters. Optimizer pragmas may not appear inside a function.

Optimizer Control Pragmas

The OPTIMIZE and OPT_LEVEL pragmas control which functions are optimized, and which set of optimizations are performed. These pragmas can be placed before any function definitions and override any previous pragma. These pragmas cannot raise the optimization level above the level specified in the command line.

OPT_LEVEL 0, 1, and 2 provide more control over optimization than the +O1 and +O2 compiler options because these pragmas can be used to raise or lower optimization at a function by function level inside the source file using different levels for different functions. Whereas, the compiler options can only be used for an entire source file. (OPT_LEVEL 3 and 4 can only be used at the beginning of the source file.)

Table 4-6 “Optimization Level Precedence ” shows the possible combinations of options and pragmas and the resulting optimization levels. The level at which a function will be optimized is the lower of the two values specified by the command line optimization level and the optimization pragma in force.

Table 4-6 Optimization Level Precedence

Command-line Optimization Level

#Pragma OPT_LEVEL

Resulting OPT_LEVEL

none

OFF

0

none

1

0

none

2

0

+O1

OFF

0

+O1

1

1

+O1

2

1

+O1

3

1

+O1

4

1

+O2

OFF

0

+O2

1

1

+O2

2

2

+O2

3

2

+O2

4

2

+O3

OFF

0

+O3

1

1

+03

2

2

+03

3

3

+03

4

3

+04

OFF

0

+04

1

1

+04

2

2

+04

3

3

+O4

4

4

 

The values of OPTIMIZE and OPT_LEVEL are summarized in Table 4-7 “Optimizer Control Pragmas ”.

Table 4-7 Optimizer Control Pragmas

Pragma

Description

#pragma OPTIMIZE ON

Turns optimization on.

#pragma OPTIMIZE OFF

Turns optimization off.

#pragma OPT_LEVEL 1

Optimize only within small blocks of code

#pragma OPT_LEVEL 2

Optimize within each procedure.

#pragma OPT_LEVEL 3

Optimize across all procedures within a source file.

#pragma OPT_LEVEL 4

Optimize across all procedures within a program.

 

Inlining Pragmas

When INLINE is specified without a functionname, any function can be inlined. When specified with functionname(s), these functions are candidates for inlining.

The NOINLINE pragma disables inlining for all functions or specified functionname(s).

The syntax for performing inlining is:

#pragma INLINE [functionname(1), ..., functionname(n)]
#pragma NOINLINE [functionname(1), ..., functionname(n)]]

For example, to specify inlining of the two subprograms checkstat and getinput, use:

#pragma INLINE checkstat, getinput

To specify that an infrequently called routine should not be inlined when compiling at optimization level 3 or 4, use:

#pragma NOINLINE opendb

See the related +O[no]inline optimization option.

Alias Pragmas

The compiler gathers information about each function (such as information about function calls, variables, parameters, and return values) and passes this information to the optimizer. The NO_SIDE_EFFECTS and ALLOCS_NEW_MEMORY pragma tell the optimizer to make assumptions it can not normally make, resulting in improved compile-time and run-time speed. They change the default information the compiler collects.

If used, the NO_SIDE_EFFECTS and ALLOCS_NEW_MEMORY pragmas should appear before the first function defined in a file and are in effect for the entire file. When used appropriately, these optional pragmas provide better optimization.

NO_SIDE_EFFECTS Pragma

By default, the optimizer assumes that all functions might modify global variables. To some degree, this assumption limits the extent of optimizations it can perform on global variables. The NO_SIDE_EFFECTS directive provides a way to override this assumption. If you know for certain that some functions do not modify global variables, you can gain further optimization of code containing calls to these functions by specifying the function names in this directive.

NO_SIDE_EFFECTS has the following form:

pragma NO_SIDE_EFFECTS functionname(1), ..., functionname(n)

All functions in functionname are the names of functions that do not modify the values of global variables. Global variable references can be optimized to a greater extent in the presence of calls to the listed functions. Note that you need the NO_SIDE_EFFECTS directive in the files where the calls are made, not where the function is defined. This directive takes effect from the line it first occurs on to the end of the file.

ALLOCS_NEW_MEMORY pragma

The ALLOCS_NEW_MEMORY pragma states that the function functionname returns a pointer to new memory that it either allocates or a routine that it calls allocates. ALLOCS_NEW_MEMORY has the following form:

pragma ALLOCS_NEW_MEMORY functionname(1), ..., functionname(n)

The new memory must be memory that was either newly allocated or was previously freed and is now reallocated. For example, the standard routines malloc() and calloc() satisfy this requirement.

Large applications might have routines that are layered above malloc() and calloc(). These interface routines make the calls to malloc() and calloc(), initialize the memory, and return the pointer that malloc() or calloc() returns. For example, in the program below:

struct_type *get_new_record(void)
{
struct_type *p;

if ((p=malloc(sizeof(*p))) == NULL) {
printf("get_new_record():out of memory\n");
abort();
}
else {
/* initialize the struct */
.
.
.
return p;
}

the routine get_new_record falls under this category, and can be included in the ALLOCS_NEW_MEMORY pragma.

FLOAT_TRAPS_ON pragma

Informs the compiler that the function(s) may enable floating-point trap handling. When the compiler is so informed, it will not perform loop invariant code motion (LICM) on floating-point operations in the function(s) named in the pragma. This pragma is required for proper code generation when floating-point traps are enabled.

#pragma FLOAT_TRAPS_ON { functionname,...functioname }
#pragma FLOAT_TRAPS_ON { _ALL }

For example:

#pragma FLOAT_TRAPS_ON xyz,abc

informs the compiler and optimizer that xyz and abc have floating-point traps turned on and therefore LICM optimization should not be performed.

[NO]PTRS_STRONGLY_TYPED Pragma

The PTRS_STRONGLY_TYPED pragma allows you to specify when a subset of types are type-safe. This provides a finer lever of control than +O[no]ptrs_strongly_typed.

#pragma PTRS_STRONGLY_TYPED BEGIN

#pragma PTRS_STRONGLY_TYPED END

#pragma NOPTRS_STRONGLY_TYPED BEGIN

#pragma NOPTRS_STRONGLY_TYPED END

Any types that are defined between the begin-end pair are taken to apply type-safe assumptions. These pragmas are not allowed to nest. For each BEGIN an associated END must be defined in the compilation unit.

The pragma will take precedence over the command line option. Although, sometimes both are required (see example 2).

Example 1

double *d;
#pragma PTRS_STRONGLY_TYPED BEGIN
int *i;
float *f;
#pragma PTRS_STRONGLY_TYPED END
main(){
........................
}

In this example only two types, pointer-to-int and pointer-to-float will be assumed to be type-safe.

Example 2

cc +Optrs_strongly_typed foo.c

/*source for Ex.2 */
double *d;
...
#pragma NOPTRS_STRONGLY_TYPED BEGIN
int *i;
float *f;
#pragma NOPTRS_STRONGLY_TYPED END
...
main(){
...
}

In this example all types are assumed to be type-safe except the types bracketed by pragma NOPTRS_STRONGLY_TYPED. The command line option is required because the default option is +Onoptrs_strongly_typed.

© Hewlett-Packard Development Company, L.P.