/Ostring
The /O options give you control over the optimizing procedures that the compiler performs. The string argument is one or more letters, with no intervening spaces, from the following table:
Letter | Optimizing Procedure |
/Oa | Assume no aliasing |
/Ow | Assume aliasing across function calls |
/Obn | Control inline expansion, where n is a digit from 0 through 2 |
/Oc | Enable block-level common subexpression optimization (default) |
/Og | Enable global-level common subexpression optimization |
/Od | Turn off all optimization |
/Oe | Ignore register keyword and allow compiler to perform global register allocation |
/Of | Turn on p-code quoting (default) |
/Of- | Turn off p-code quoting |
/Oi | Generate intrinsic functions |
/Ol | Enable loop optimization |
/On | Turn off potentially unsafe loop optimizations |
/Oz | Turn on potentially unsafe loop optimizations |
/Oo | Turn on post code-generation optimizing (default) |
/Oo- | Turn off post code-generation optimizing |
/Op | Improve float consistency |
/Oq | Turn on p-code optimization |
/Or | Enable single exit point from functions (useful when debugging with CodeView) |
/Os | Minimize executable file size |
/O, /Ot | Minimize execution speed (default) |
/Ov | Sort local variables by frequency of use, p-code only (default) |
/Ov- | Sort local variables in the order that they occur, p-code only |
/Ox | Maximize optimization |
With the exception of the minus switches, /Of–, /Oo–, and /Ov–, the letters following the /O, including bn, can appear in a continuous series in any order. When there is a conflict, the compiler uses the last /O option given. Each option applies to all source files following it on the command line.
Note:
If you are using the debugger, you may want to set the /Od option. If you don't specify /Od, some forms of the compiler perform code-movement optimizations, possibly making it difficult for you to follow your program in the debugger.
/Oa and /Ow (Assuming No Aliasing )
An “alias” is a name used to refer to a memory location already referred to by a different name. Because a memory access requires more time than is required to access the CPU's registers, the compiler tries to store frequently used variables in registers. Aliasing, however, reduces the extent to which a compiler can keep variables in registers.
The /Oa option tells the compiler to ignore the possibility of multiple aliases for a memory location. In the list that follows, the term “reference” means read or write; that is, whether a variable is on the left side of an assignment statement or the right side, you are still referring to it. In addition, any function calls that use a variable as a parameter are references to that variable. When you tell the compiler to assume that you are not doing aliasing, it expects that the following rules are being followed for any variable not declared as volatile:
If a variable is used directly, no pointers are used to reference that variable.
If a pointer is used to refer to a variable, that variable is not referred to directly.
If a pointer is used to modify a memory location, no other pointers are used to access the same memory location.
Both the /Oa and /Ow options tell the compiler that you have not used aliases in your code. When you use /Oa, you specify that you will not be doing any aliasing (which allows the compiler to perform significant optimizations that might not otherwise have been possible), and that function calls are safe. When you use the /Ow option, you specify that aliasing might occur across function calls. Therefore, after each function call, pointer variables must be reloaded from memory. For more information on the /Oa and /Ow options and aliasing, see the Programming Techniques manual.
Aliasing bugs most frequently show up as corruption of data. If you find that global or local variables are being assigned seemingly random values, take the following steps to determine if you have a problem with optimization and aliasing:
Compile the program with /Od (disable optimizations).
If the program works when compiled with the /Od option, check your normal compile options for the /Oa option (assume no aliasing).
If you were using the /Oa option, fix your compile options so that /Oa is not specified.
Note:
You can instruct the compiler to disable unsafe optimizations with code that does aliasing by using the optimize pragma with the a or w option.
/Obn (Control Inline Expansion)
Use the /Ob option to control the inline expansion of functions, where n is a digit from 0 though 2. The following table describes the action of each digit.
Table 13.8 Inline Expansion Control
Digit | Action |
0 | Disables inline expansion (default with /Od) |
1 | Only expand functions marked as inline or __inline or in a C++ member function defined within a class declaration (default without /Od) |
2 | Expand functions marked as inline or __inline and any other function that the compiler chooses (expansion occurs at compiler discretion) |
/Oc and /Og (Enable Common Subexpression Optimization)
Use of either the /Oc or the /Og option allows the compiler to calculate the value of a common subexpression once. For example, b + c is common to the following code. If the values of b and c do not change between the three expressions, the compiler can calculate the value of b + c once, assign the calculation to a temporary variable, and substitute the variable as appropriate.
a = b + c;
d = b + c;
e = b + c;
When you use the /Oc option (default common subexpression optimization), the compiler examines short sections of code (basic blocks) for common subexpressions. When you use the /Og option (enable global common subexpression optimization), the compiler searches entire functions for common subexpressions. You can disable the default common subexpression optimization with the /Od option. For more information about common subexpression optimization, see Chapter 1 in the Programming Techniques manual.
Note:
You can enable or disable block-scope common subexpression optimization on a function-by-function basis using the optimize pragma with the c option. You can enable or disable global common subexpression optimization on a function-by-function basis using the optimize pragma with the g option.
The /Od option tells the compiler to turn off all optimizations in the program, which speeds compilation. Use the /Od option when you compile with the /Zi option (described on topic ) to include debugging information. The /Od option does not reorganize code, making it easier to debug.
/Oe (Global Register Allocation)
The /Oe option instructs the compiler to ignore the register keyword and to allocate registers based on how often they are used. This allows the compiler to store frequently used variables and subexpressions in registers.
/Of (Turn On and Turn Off P-Code Quoting)
The /Of option (p-code only) enables the compiler to find duplicate sections of code and then create a single instance of that code. This process is known as “quoting.” With quoting enabled (/Of), the duplicate code is replaced with the p-code equivalent of a function call to produce smaller code than is produced when quoting is disabled (/Of–).
Quoting enabled (/Of) is the default. However, quoting makes code difficult to read; use the /Of– option to disable quoting while debugging. Quoting is especially useful for a final product.
/Oi (Generate Intrinsic Functions)
The /Oi option instructs the compiler to replace the following function calls with their inline forms:
Target | Target | ||||||||
Function | 16 bit | 32 bit | Function | 16 bit | 32 bit | ||||
_alloca | no | yes | _outpw | yes | yes | ||||
_disable | yes | yes | _rotl | yes | yes | ||||
_enable | yes | yes | _rotr | yes | yes | ||||
_fmemcmp | yes | no | _setjmp | no | yes | ||||
_fmemcpy | yes | no | _strset | yes | yes | ||||
_fmemset | yes | no | abs | yes | yes | ||||
_fstrcat | yes | no | fabs | yes | yes | ||||
_fstrcmp | yes | no | labs | yes | yes | ||||
_fstrcpy | yes | no | memcmp | yes | yes | ||||
_fstrlen | yes | no | memcpy | yes | yes | ||||
_fstrset | yes | no | memset | yes | yes | ||||
_inp | yes | yes | strcat | yes | yes | ||||
_inpw | yes | yes | strcmp | yes | yes | ||||
_lrotl | yes | yes | strcpy | yes | yes | ||||
_lrotr | yes | yes | strlen | yes | yes | ||||
_outp | yes | yes | , |
Programs that use intrinsic functions are faster because they do not include the overhead associated with function calls. However, they may be larger due to the additional code generated.
Intrinsic versions of the memset, memcpy, and memcmp functions in compact- and large-model programs cannot handle huge arrays or huge pointers. To use huge arrays or huge pointers with these functions, you must compile your program with either the huge memory model from PWB or with the /AH option on the command line.
With /Oi, you cannot link to an alternate math library. Also, 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 onto the usual normal argument stack:
Target | Target | ||||||||
Function | 16 bit | 32 bit | Function | 16 bit | 32 bit | ||||
acos | yes | yes | _acosl | yes | no | ||||
asin | yes | yes | _asinl | yes | no | ||||
atan | yes | yes | _atanl | yes | no | ||||
atan2 | yes | yes | _atan2l | yes | no | ||||
ceil | yes | no | _ceill | yes | no | ||||
cos | yes | yes | _cosl | yes | no | ||||
cosh | yes | yes | _coshl | yes | no | ||||
exp | yes | yes | _expl | yes | no | ||||
floor | yes | no | _floorl | yes | no | ||||
fmod | yes | yes | _fmodl | yes | no | ||||
log | yes | yes | _logl | yes | no | ||||
log10 | yes | yes | _log10l | yes | no | ||||
pow | yes | yes | _powl | yes | no | ||||
sin | yes | yes | _sinl | yes | no | ||||
sinh | yes | yes | _sinhl | yes | no | ||||
sqrt | yes | yes | _sqrtl | yes | no | ||||
tan | yes | yes | _tanl | yes | no | ||||
tanh | yes | yes | _tanhl | yes | no |
For more information on intrinsic functions, see Chapter 1 in the Programming Techniques manual.
The /Ol option enables a set of loop optimizations that move or rewrite code so that it executes more quickly. Because loops involve sections of code that are executed repeatedly, they are targets for optimization.
The /Ol option removes invariant code. An optimal loop contains only expressions whose values change through each execution of the loop. Any subexpression whose value is constant should be evaluated before the body of the loop is exe-cuted. Unfortunately, these subexpressions are not always readily apparent. The optimizer can remove many of these expressions from the body of a loop at compile time. This example illustrates invariant code in a loop:
i = -100;
while( i < 0 )
{
i += x + y;
}
In the preceding example, the expression x + y does not change in the loop body. Loop optimization removes this subexpression from the body of the loop so that it is only executed once, not every time the loop body is executed. The optimizer changes the code to the following:
i = -100;
t = x + y;
while( i < 0 )
{
i += t;
}
Loop optimization is much more effective when the compiler can assume no aliasing. While you can use loop optimization without the /Oa or /Ow option, use /Oa to ensure that the most options possible are used.
Here is a code fragment that could have an aliasing problem:
i = -100;
while( i < 0 )
{
i += x + y;
*p = i;
}
If you do not specify the /Oa option for the preceding code, the compiler must assume that either x or y could be modified by the assignment to *p. Therefore, the compiler cannot assume the subexpression x + y is constant for each loop iteration. If you specify that you are not doing any aliasing (with the /Oa option), the compiler assumes that modifying *p cannot affect either x or y, and that the subexpression is indeed constant and can be removed from the loop, as in the previous example.
Note:
All loop optimizations specified by the /Ol option are safe optimizations. To enable aggressive loop optimizations, you must use the enable aggressive optimizations (/Oz) option. While the optimizations enabled by the combination of /Ol and /Oz are not safe for all cases, they do work properly for most programs.
/Oo, /Oo- (Enable and Disable Post-Code-Generation Optimizing)
The /Oo option allows the compiler to perform the following optimizations after code generation has occurred:
Peepholes
Code motion
Dead code removal
Unused locals removal
Register reloading removal
Exit sequence
Branch shortening
The /Oo– option disables the optimizations. The following table shows the default state of the /Oo option and its state with the p-code option (/Oq) and the Fast Compile option (/f):
Compiler | Default |
Optimizing | On |
P-Code | On |
Fast Compile | Off |
/On (Turn Off Potentially Unsafe Loop Optimizations)
The /On option disables unsafe loop optimizations by preventing some constant expressions in a loop from being moved out of the loop. Since the /Ol option automatically implies /On, you do not need to specify /On explicitly; it is provided for compatibility with earlier versions of Microsoft C.
/Oz (Turn On Maximum Loop Optimization)
The /Oz option aggressively removes as many invariant expressions as possible from a loop. If you do not specify /Oz, the /Ol option removes only the invariant expressions guaranteed to be executed in every iteration of the loop. Do not use /Oz if you suspect that a loop optimization has caused an error.
/Op (Improve Float Consistency)
The primary use of the /Op option is to improve the consistency of tests for equality and inequality. Without the /Op option, the compiler usually uses coprocessor registers to hold the intermediate results of floating-point calculations. Such optimization increases program speed and decreases program size.
The coprocessor has 80-bit registers; the memory representation can be 32, 64, or 80 bits. Therefore, storing intermediate results in registers can provide a greater degree of precision than storing them in memory.
When you use the /Op option, the compiler loads data from memory prior to each floating-point operation and, if assignment occurs, writes the results back to memory upon completion. Loading the data prior to each operation guarantees that the data does not retain any significance greater than the capacity of its type.
A program compiled with /Op may be slower and larger than one compiled without /Op.
/Oq (Turns On P-Code Optimization)
The /Oq option optimizes your code for size by compiling the program into an alternate form called “p-code.” P-code produces much smaller programs than machine code, but your machine cannot execute them directly. Programs compiled into p-code are executed by a small run-time interpreter incorporated into your executable file. P-code does not support initialized static huge data.
You can also directly control aspects of p-code optimization. You can control which sections of the program get compiled into p-code using the optimize pragma and the /Oq option together.
For example,
#pragma optimize ("q", on)
// Functions compiled into p-code
#pragma optimize ("q", off)
// Remaining functions compiled into machine code
These pragmas are ignored if the program is not compiled with the /Oq option.
Since p-code runs more slowly than machine language, you may want to have the speed-critical sections of your program compiled into machine language.
Note:
The /Oq option is not compatible with any of the following options: /FPa, /FPc, /FPc87, /Fs, /Gr, /Sl, /Sp, /Ss, or /St.
/Or (Common Function-Exit Sequence)
This option causes all returns within a function to use a common exit sequence at the end of the function. This allows you to set a CodeView breakpoint on the closing brace (}) of the function rather than on every return statement within the function. This can be used, for example, to quickly get to the end of a function you wish to bypass.
Note:
The /Or option is useful only when using CodeView; do not use it when generating code for a finished product.
/Os (Minimize Executable File Size)
The /Os option minimizes the size of executable files; it produces smaller but possibly slower code. If you do not select this option, code is larger but may be faster.
/O and /Ot (Minimize Execution Time)
When you do not use any of the /O options, the CL command automatically optimizes for program execution speed. The /O and /Ot options have the same effect as this default.
Wherever the compiler has a choice between producing smaller (but perhaps slower) and larger (but perhaps faster) code, the compiler generates faster code. For example, when you specify the /Ot option, the compiler generates either library calls to the operating system or inline code to perform shift operations on long operands.
/Ov, /Ov- (Specify Type of Frame Sorting)
The compiler reduces the size of p-code programs by using 1-byte opcodes to reference local variables. These opcodes are frame-relative addresses, and only a limited number of them are available for each function. The optimizer uses one of two algorithms to determine which variables receive the available opcodes.
Option | Description |
/Ov | Sorts the local variables by frequency of use (default) |
/Ov– | Sorts the local variables in the order that they occur (lexical order) |
/Ox (Use Maximum Optimization)
The /Ox option is a shorthand way to combine optimizing options to produce the fastest possible program. Its effect is the same as using the following options on the same command line:
/Ob1cegilnot /Gs
Example
CL /Ox FILE.C
This command tells the compiler to use the optimizing compiler to compile FILE.C with the following options:
Option | Description |
/Ob1 | Expand functions marked as inline or __inline or those in a C++ member function defined within a class declaration |
/Oc | Enable local common subexpression elimination |
/Oe | Allow global register allocation |
/Og | Enable global common subexpression elimination |
/Oi | Generate intrinsic functions |
/Ol | Perform loop optimizations |
/On | Turn off potentially unsafe loop optimizations |
/Oo | Enable post code-generation optimizing |
/Ot | Favor execution time over code size |
/Gs | Remove stack probes |