The best way to use the compiler's optimization features is toleave the defaults on and let the compiler worry about the rest. There are some thingsa where a bit more information may help you select compiler optimization settings.
Space verses Time optimization
The best thing to do here is always use space optimization exceptwhen test timings show a difference in compute intensive code. The compiler nevergenerates slow code with space optimization. Time optimization does some things differentlybecause they are technically faster, although larger in code generation size, andmight make a difference in performance. Even when you do use the option you willprobably only be using the option on a few modules, where all others are using spaceoptimization.
Effects of time optimization
Conditional common sub-expression elimination
Some expression classes are only a "winner" to do ifthe sub expression gets assigned to a register.
This option can slow down compile times by about 20%. This isbecause almost everything becomes a subexpression to be dealt with later by the registerallocator. This gives the optimizer many more expressions manipulate, and adds workfor the register allocator to resolve.
This option is enabled by default for 32-bit code because itgenerally finds good things to do on most code. This option is marginal at best on16-bit code and therefore is defaulted off. You can try the option on 16-bit codeto see if you get any savings in code size.
Variable lifetime analysis and dead store elimination
Variable lifetime analysis and dead store optimization are tiedtogether. If one is off, then the other will not be done.
IA-32 architecture register parameter passing
No forward referenced procedure will ever get register parameterpassing. It is therefore better to edit your files so that all procedures where possibleare implemented before called to maximize register parameter passing within a sourcefile. In Ada95 this is a requirement of the language, not so for Modula-2. In Ada95and Modula-2 if you use the FORWARD keyword to forward declare a procedure that procedurewill not get register parameter passing.
Not getting register parameter passing does not mean that a parameterwill not be enregistered by the compiler. In these cases the compiler will move theparameter to its register immediately at the top of the procedure and reference theregister from that point on.
Stony Brook compilers do not perform algorithm register parameterpassing because the IA-32 architecture is too strange to allow this without needingto shuffle these algorithm parameters to a proper area, such as another registeror on to the stack, based on the register needs of the procedure in question. Thisalso allows our compilers to parameter pass any parameter, in any register, at anytime, and not just a limited few given by algorithm.
Cross module register usage
Note: Cross module register usage should only be used as a finalbuild option. It causes almost all modules to be built even if you only change oneprocedure within one file. This is because details of the actual implementation,code generation, of the procedure is being made to all modules. Changing a procedurecan change register allocation which can change the parameter passing (IA-32 only)to that procedure.
Cross module register usage can increase code size if the implementationof a module is not compiled before any other modules that refer to the definition/specificationportion of a module. This is because the compiler writes the implementation detailsof each procedure into the symbol file.
The environment build system is designed to optimize the capabilitiesof cross module register usage. Other make systems, unless hand edited, will be inadequate.
IA-32 Architecture cross module register parameter passing
The compiler generates procedure stubs that will allow both stackbased and register based cases to work, but more code will be linked into the applicationif the definitions are referred to before the implementation is compiled. Also forcross module register usage to function properly the module must be compiled withthe output file option set to LIB. The reason being the compiler generates two proceduresfor all exported procedures. One by user name and one by a compiler generated name.The user name procedure takes all parameters on the stack and then passes these parametersin the proper registers to the compiler generated named procedure, which containsthe actual procedure code, which accepts register parameters.
All accesses to exported procedures other than a procedure callwill reference the non register parameter passing procedure stub. All procedure callswill reference the register parameter version, if the register parameter info isin the symbol file, otherwise it will call the non register parameter stub. Thisis why compilation order is so important.
The reason for using the LIB compiler option, and therefore enablesmart linking, is to be able not link in all of the non register parameter pass procedurestubs that are not referenced, because in a reasonable situation none of these shouldever be called, or at least only a very small few.