Optimization

From Lazarus wiki
Jump to navigationJump to search

For an overview of optimization possibilities, see Chapter 11 of the Free Pascal Programmer's Guide.

Free Pascal allows you to use a set of straightforward compiler directives or commandline arguments to considerably power up your programs. (While running debug builds, you may want to keep most code optimizations off to enjoy faster compilation speeds and avoid rare unintended side effects.)


Target Processor

By default, FPC selects a conservative minimum target for code generation, to maximize compatibility. A higher target processor enables the compiler to use different instructions that would not be available on lower processors. How high you want to set the minimum target processor depends on your target audience. To set this, use "-Cp<CPU>". For example, on the x86 architecture, -CpPENTIUMM gives the compiler plenty of room and still covers almost all users.

The compiler can also produce code generally favoring a particular processor, but without requiring that processor as a hard minimum. To set this, use "-Op<CPU>".

To check which processors your compiler version supports, run "fpc -ic".


Target FPU

FPU here encompasses the old x87 floating point unit, as well as modern SSE and AVX SIMD instruction sets. All programs benefit from enabling SIMD instructions, which immediately speed up large array operations without needing to change any code in your program. But older CPUs don't support the latest SIMD instruction sets, so the choice is a tradeoff between compatibility with old CPUs and faster operations on current CPUs. By default, FPC uses the conservative minimum FPU, to maximize compatibility. To set this, use "-Cf<FPU>".

Note also that these SIMD instructions are primarily for x86/amd64 architectures. Other architectures like ARM or PowerPC have different SIMD options, which may become relevant when porting a program to a different architecture.

To check which FPU instruction sets your compiler version supports, run "fpc -if".

To help decide which instruction sets it makes sense to target:

  • SSE is available since Pentium 3 from 1999
  • SSE2 is available since Pentium 4 from 2000 or AMD Opteron from 2003
  • SSE64 (SSE2 on amd64) is available on all amd64 from 2004
  • SSE3 is also available from 2004
  • SSSE3 is available since Intel Core from 2006 or AMD Bobcat/Bulldozer from 2011
  • SSE41 is available since Intel Core 2 from 2007 or AMD Bulldozer from 2011
  • SSE42 is available since Intel Core i from 2008 or AMD Bulldozer from 2011
  • AVX is available since Intel Sandy Bridge from 2011 or AMD Bulldozer from 2011
  • AVX2 is available since Intel Haswell from 2013 or AMD Excavator from 2015


Optimization Switches

You can enable general optimization groups using "-O1", "-O2", "-O3", and "-O4". Individual switches can be enabled with "-Oo<switch>".

As of 13 July 2020, the optimization groups (defined in /compiler/<arch>/cpuinfo.pas, which references /compiler/globtype.pas) are:

-O1: PEEPHOLE

-O2: O1 + REMOVEEMPTYPROCS + UNUSEDPARA + REGVAR + STACKFRAME + TAILREC + CSE

-O3: O2 + CONSTPROP + DFA + USELOADMODIFYSTORE + LOOPUNROLL

-O4: O3 + ORDERFIELDS + DEADVALUES + FASTMATH + USEEBP/USERBP

Ungrouped: UNCERTAIN, SIZE, STRENGTH, SCHEDULE, AUTOINLINE, DEADSTORE, FORCENOSTACKFRAME

WARNING: In FPC 3.2.0, the -O3 and -O4 options produce compilation errors on Windows in some cases. Furthermore, the ungrouped and -O4 group have potential side effects and may break your code, so use responsibly.

WARNING: In FPC 3.2.0 and 3.2.2, dead store optimization is known to produce bad code in some cases. Avoid using it for now.

To check which switches your compiler version supports, run "fpc -io".


Optimization in Code

You can control what optimization happens in your code, eg. {$optimization noloopunroll}. The following are defined in compiler/globtypes.pas.

LEVEL1, LEVEL2, LEVEL3, LEVEL4, REGVAR, UNCERTAIN, SIZE, STACKFRAME, PEEPHOLE, LOOPUNROLL, TAILREC, CSE, DFA, STRENGTH, SCHEDULE, AUTOINLINE, USEEBP, USERBP, ORDERFIELDS, FASTMATH, DEADVALUES, REMOVEEMPTYPROCS, CONSTPROP, DEADSTORE, FORCENOSTACKFRAME, USELOADMODIFYSTORE, UNUSEDPARA

Putting 'NO' in front of any of those options has the opposite effect.


Notes

To take optimization a step further, see Whole Program Optimization.

If you are interested in optimizing for size rather than speed, see Size Matters.

Vectorization is a powerful feature, but still a work in progress. You can already use SIMD instructions in inline assembly.