Compiler User GuideConventions and Feedback Overview of the Compiler Getting Started with the Compiler Compiler Features Compiler Coding Practices The compiler as an optimizing compiler Compiler optimization for code size versus speed Compiler optimization levels and the debug view Selecting the target CPU at compile time Optimization of loop termination in C code Loop unrolling in C code Compiler optimization and the volatile keyword Code metrics Code metrics for measurement of code size and data Stack use in C and C++ Benefits of reducing debug information in objects Methods of reducing debug information in objects a Guarding against multiple inclusion of header file Methods of minimizing function parameter passing o Functions that return multiple values through regi Functions that return the same result when called Comparison of pure and impure functions Recommendation of postfix syntax when qualifying f Inline functions Compiler decisions on function inlining Automatic function inlining and static functions Inline functions and removal of unused out-of-line Automatic function inlining and multifile compilat Restriction on overriding compiler decisions about Compiler modes and inline functions Inline functions in C++ and C90 mode Inline functions in C99 mode Inline functions and debugging Types of data alignment Advantages of natural data alignment Compiler storage of data objects by natural byte a Relevance of natural data alignment at compile tim Unaligned data access in C and C++ code The __packed qualifier and unaligned data access i Unaligned fields in structures Performance penalty associated with marking whole Unaligned pointers in C and C++ code Unaligned Load Register (LDR) instructions generat Comparisons of an unpacked struct, a __packed stru Compiler support for floating-point arithmetic Default selection of hardware or software floating Example of hardware and software support differenc Vector Floating-Point (VFP) architectures Limitations on hardware handling of floating-point Implementation of Vector Floating-Point (VFP) supp Compiler and library support for half-precision fl Half-precision floating-point number format Compiler support for floating-point computations a Types of floating-point linkage Compiler options for floating-point linkage and co Floating-point linkage and computational requireme Processors and their implicit Floating-Point Units Integer division-by-zero errors in C code About trapping integer division-by-zero errors wit About trapping integer division-by-zero errors wit Identification of integer division-by-zero errors Examining parameters when integer division-by-zero Software floating-point division-by-zero errors in About trapping software floating-point division-by Identification of software floating-point division Software floating-point division-by-zero debugging New language features of C99 New library features of C99 // comments in C99 and C90 Compound literals in C99 Designated initializers in C99 Hexadecimal floating-point numbers in C99 Flexible array members in C99 __func__ predefined identifier in C99 inline functions in C99 long long data type in C99 and C90 Macros with a variable number of arguments in C99 Mixed declarations and statements in C99 New block scopes for selection and iteration state _Pragma preprocessing operator in C99 Restricted pointers in C99 Additional <math.h> library functions in C99 Complex numbers in C99 Boolean type and <stdbool.h> in C99 Extended integer types and functions in <inttyp <fenv.h> floating-point environment access i <stdio.h> snprintf family of functions in C9 <tgmath.h> type-generic math macros in C99 <wchar.h> wide character I/O functions in C9 How to prevent uninitialized data from being initi Compiler Diagnostic Messages Using the Inline and Embedded Assemblers of the AR
Compiler optimization and the volatile keyword
Higher optimization levels can reveal problems in some programs that are not apparent at lower optimization levels, for example, missing volatile qualifiers. This can manifest itself in a number of ways. Code might become stuck in a loop while polling hardware, multi-threaded code might exhibit strange behavior, or optimization might result in the removal of code that implements deliberate timing delays. In such cases, it is possible that some variables are required to be declared as volatile.
The declaration of a variable as volatile tells the compiler that the variable can be modified at any time externally to the implementation, for example, by the operating system, by another thread of execution such as an interrupt routine or signal handler, or by hardware. Because the value of a volatile-qualified variable can change at any time, the actual variable in memory must always be accessed whenever the variable is referenced in code. This means the compiler cannot perform optimizations on the variable, for example, caching its value in a register to avoid memory accesses. Similarly, when used in the context of implementing a sleep or timer delay, declaring a variable as volatile tells the compiler that a specific type of behavior is intended, and that such code must not be optimized in such a way that it removes the intended functionality.
In contrast, when a variable is not declared as volatile, the compiler can assume its value cannot be modified in unexpected ways. Therefore, the compiler can perform optimizations on the variable.
The use of the volatile keyword is illustrated
in the two sample routines of Table 7. Both of these routines loop reading
a buffer until a status flag
The two versions of the routine differ only in the way that
Table 7. C code for nonvolatile and volatile buffer loops
Table 8 shows
the corresponding disassembly of the machine code produced by the
compiler for each of the sample versions in Table 3, where the
C code for each implementation has been compiled using the option
Table 8. Disassembly for nonvolatile and volatile buffer loop
In the disassembly of the nonvolatile version of the buffer
loop in Table 8, the
In contrast, in the disassembly of the volatile version of
the buffer loop, the compiler assumes the value of
To avoid optimization problems caused by changes to program state external to the implementation, you must declare variables as volatile whenever their values can change unexpectedly in ways unknown to the implementation.
In practice, you must declare a variable as volatile whenever you are:
The compiler does not optimize the variables you have declared as volatile.