 |
» |
|
|
 |
Before exploring the
various optimizations that are performed, it is important to review
the coding guidelines used to assist the optimizer. This section
is broken down into the following subsections: General
guidelines |  |
The coding guidelines presented in this section help the optimizer
to optimize your program, regardless of the language in which the
program is written. 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 “+O[no]initcheck” for related information. Use constants instead of variables in arithmetic
expressions such as shift, multiplication, division, or remainder
operations. Position the loop inside the procedure or use a
directive to call the loop in parallel, when a loop contains a procedure
call. Construct loops so the induction variable increases
or decreases toward zero where possible. The code generated for
a loop termination test is more efficient with a test against zero
than with a test against some other value. Do not reference outside the bounds of an array.
Fortran provides the -C option to check whether your program references
outside array bounds. Do not pass an incorrect number of arguments to
a function.
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 possible. Use unsigned variables rather than signed, when
using short or char variables or bit-fields. This is more efficient
because a signed variable causes an extra instruction to be generated. Pass and return pointers to large structs instead
of passing and returning large structs by value, where possible. 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 are accessed indirectly
through a pointer or by another function call are: Global variables (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, the
preceding assumption should not pose a problem. 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 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 assumes 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,
as 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.
Additionally, 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.
For more information regarding coding guidelines, see “General
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 are accessed (directly or indirectly) are: COMMON variables declared in the routine Parameters to this routine
Local variables include all static and nonstatic variables. In general, you do not need to be concerned about the preceding assumption.
However, if you have code that violates it, the optimizer can adversely
affect the behavior of the program. Avoid using variables that are 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 Fortran. Also avoid using extensive equivalencing and memory-mapping
schemes, where possible. See the section “General
guidelines” for additional guidelines.
|