Using the Optimiser

Using
the
Optimiser
The underlying assembler code produced by the compiler is the single most important element to a good language because compact assembler not only means more can be squeezed into the tight confines of the microcontroller, but also the code runs faster which allows more complex operations to be performed. This is why the compiler now has a “dead code removal” pass as standard which will remove redundant mnemonics, and replace certain combinations of mnemonics with a single mnemonic. WREG tracking is also implemented as standard which helps eliminate unnecessary loading of a constant value into the WREG SFR.
And even though the compiler already produces good underlying assembler mnemonics, there is always room for improvement, and that improvement is achieved by a separate optimising pass.
The optimiser is enabled by issuing the Declare: -
Declare Optimiser_Level = n
Where n is the level of optimisation required.
The Declare should be placed at the top of the BASIC program, but anywhere in the code is actually acceptable because once the optimiser is enabled it cannot be disabled later in the same program.
As of version 3.3.3.0 of the compiler, the optimiser has 3 levels, 4 if you include Off as a level.
Level 0 disables the optimiser.
Level 1 Chooses the appropriate branching mnemonics when using an 18F device, and actively chooses the appropriate page switching mnemonics when using a 14-bit core (16F) device.
This is the single most important optimising pass for larger microcontrollers. For 18F types it will replace Call with RCall and GoTo with Bra whenever appropriate, saving 1 byte of code space every time.
Level 2 Further re-arranging of branching operations.
Level 3 18F devices only. Re-arranges conditional branching operations. This is an important optimising pass because a single program can implement many decision making mnemonics.
You must be aware that optimising code, especially paged code found in the larger standard 14-bit core (16F) devices can, in some circumstances, have a detrimental effect on a program if it misses a page boundary, this is true of all optimisation on all compilers and is something that you should take into account. This is why the standard 14-bit core optimiser is not an official part of the compiler, and has been left in place because of current user requests.
Always try to write and test your program without the optimiser pass. Then once it’s working as expected, enable the optimiser a level at a time. However, this is not always possible with larger programs that will not fit within the microcontroller without optimisation. In this circumstance, choose level 1 optimisation whenever the code is reaching the limits of the microcontroller, testing the code as you go along.
Caveats
Of course there’s no such thing as a free lunch, and there are some features that cannot be used when implementing the optimiser.
The main one is that the optimiser is not supported with 12-bit core devices.
Also, the assembler’s Org directive is not allowed with 14-bit core (16F) devices when using the optimiser, but can be used with 18F devices with care.
When using 18F devices, do not use the Movfw macro as this will cause problems within the Asm listing, use the correct mnemonic of Movf Var,w.
On all devices, do not use the assembler LIST and NOLIST directives, as the optimiser uses these to sculpt the final Asm used.
Declare Dead_Code_Remove = On/Off
The above declare removes some redundant op-codes from the underlying Asm code.
Removal of redundant RAM Bank Switching mnemonics. Removal of redundant Movwf mnemonics if preceded by a Movf Var,w mnemonic. Removal of redundant Movf Var,W mnemonics if preceded by a Movwf mnemonic. Removal of redundant Andlw mnemonics if preceded by another Andlw mnemonic. Replaced a Call-Return mnemonic pair with a single GoTo mnemonic.