Jump to content United States-English
HP.com Home Products and Services Support and Drivers Solutions How to Buy
» Contact HP
More options
HP.com home
Fortran 90, Fortran 77, C, aC++: Exemplar Programming Guide > Chapter 3 Compiler optimizations

Using the optimizer

» 

Technical documentation

Complete book in PDF
» Feedback
Content starts here

 » Table of Contents

 » Glossary

Before exploring the various optimizations that are performed, we should examine what coding guidelines can be followed to assist the optimizer. This section is broken down into the following subsections:

  • General guidelines

  • Fortran 90 and Fortran 77 guidelines

  • C and C++ guidelines

General guidelines

The coding guidelines presented in this section help the optimizer to optimize your program, regardless of the language the program is written in.

  • Where possible, use local variables to help the optimizer promote variables to registers.

  • Do not use local variables before they are initialized. When you request +O2, +O3, or +O4 optimizations, the compiler tries to detect and indicate violations of this rule. See the section +O[no]initcheck for related information.

  • Where possible, use constants instead of variables in arithmetic expressions such as shift, multiplication, division, or remainder operations.

  • If a loop contains only a procedure call, position the loop inside the procedure or use a directive to call the loop in parallel—if appropriate.

  • The code generated for a loop termination test is more efficient with a test against zero than with a test against some other value. Therefore, where possible, construct loops so the control variable increases or decreases toward zero.

  • Avoid referencing outside the bounds of an array. (Fortran provides the -C option to check whether your program references outside array bounds.)

  • Avoid passing an incorrect number of arguments to functions.

Fortran guidelines

The coding guidelines presented in this section help the optimizer to optimize Fortran programs.

As part of the optimization process, the compiler gathers information about the use of variables and passes this information to the optimizer. The optimizer uses this information to ensure that every code transformation maintains the correctness of the program, at least to the extent that the original unoptimized program is correct.

When gathering this information, the compiler assumes that inside a routine (either a function or a subroutine) the only variables that can be accessed (directly or indirectly) are:

  • COMMON variables declared in the routine

  • Local variables

  • Parameters to this routine

Local variables include all static and nonstatic variables.

In general, you do not need to be concerned about this assumption. However, if you have code that violates the assumption, the optimizer can change the behavior of the program in an undesirable way.

One guideline is to avoid using variables that can be accessed by a process other than the program. The compiler assumes that the program is the only process accessing its data. The only exception is the shared COMMON variable. In this case, optimization will be correct if you properly use the $OPTIMIZE ASSUME_NO_SHARED_COMMON_PARMS Fortran 77 directive. For more information on OPTIMIZE directives, see Appendix A, "Appendix A “Standard HP compiler
directives and pragmas”
."

A final guideline is to avoid using extensive equivalencing and memory-mapping schemes, where possible.

See the section “General guidelines” for additional guidelines.

C and C++ guidelines

The coding guidelines presented in this section help the optimizer to optimize your C and C++ programs.

  • Use do loops and for loops in place of while loops. do loops and for loops are more efficient because opportunities for removing loop-invariant code are greater.

  • Use register variables where needed.

  • When using short or char variables or bit-fields, it is more efficient to use unsigned variables rather than signed because a signed variable causes an extra instruction to be generated.

  • Whenever possible, pass and return pointers to large structs instead of passing and returning large structs by value.

  • Use type-checking tools like lint to help eliminate semantic errors.

  • Use local variables for the upper bounds (stop values) of loops; using local variables may enable the compiler to optimize the loop.

During optimization, the compiler gathers information about the use of variables and passes this information to the optimizer. The optimizer uses this information to ensure that every code transformation maintains the correctness of the program, at least to the extent that the original unoptimized program is correct.

When gathering this information, the compiler assumes that while inside a function, the only variables that can be accessed indirectly through a pointer or by another function call are:

  • Global variables (that is, all variables with file scope)

  • Local variables that have had their addresses taken either explicitly by the & operator, or implicitly by the automatic conversion of array references to pointers

In general, you do not need to be concerned about this assumption. Standard-compliant C and C++ programs do not violate this assumption. However, if you have code that does violate this assumption, the optimizer can change the behavior of the program in an undesirable way. In particular, you should follow the coding practices below to ensure correct program execution for optimized code:

  • Avoid using variables that are accessed by external processes. Unless a variable is declared with the volatile attribute, the compiler will assume that a program's data is accessed only by that program. Using the volatile attribute may significantly slow down a program.

  • Avoid accessing an array other than the one being subscripted. For example, the construct a[b-a], where a and b are the same type of array, actually references the array b, because it is equivalent to *(a+(b-a)), which is equivalent to *b. Using this construct might yield unexpected optimization results.

  • Avoid referencing outside the bounds of the objects a pointer is pointing to. All references of the form *(p+i) are assumed to remain within the bounds of the variable or variables that p was assigned to point to.

  • Do not rely on the memory layout scheme when manipulating pointers; incorrect optimizations may result. For example, if p is pointing to the first member of a structure, do not assume that p+1 points to the second member of the structure. Another example: if p is pointing to the first in a list of declared variables, p+1 is not necessarily pointing to the second variable in the list.

See the section “General guidelines” for additional guidelines.

Printable version
Privacy statement Using this site means you accept its terms Feedback to webmaster
© Hewlett-Packard Development Company, L.P.