Code Generation and Optimization Options - Code Generation and Optimization Options - 57222

AOCC User Guide

Document_ID
57222
Release_Date
2026-05-12
Revision
5.2 English

Both Clang and Flang rely on AOCC optimizer and code generator stages to transform the LLVM IR and generate the best code for the target x86 platform.

Optimization options categorized by type are listed here.

Optimization Level Options

  • -O0

    No optimization: this level compiles the fastest and generates the most debuggable code.

  • -O1

    Between levels -O0 and -O2.

  • -O2 

    Default option and enables most optimizations.

  • -O3

    Enables all optimizations which take longer to perform or may generate larger code (in an attempt to make the program run faster).

    The -O3 level in AOCC has more optimizations than the base LLVM version. These optimizations include improved handling of indirect calls and advanced vectorization.

  • -Ofast

    Enables all the optimizations from -O3 along with other aggressive optimizations that may violate strict compliance with language standards.

    The -Ofast level in AOCC has more optimizations than the base LLVM version. These optimizations include partial unswitching, improvements to inlining, and unrolling.

  • -flto
    Generates output files in LLVM formats suitable for link time optimization. When used with -S, this option generates LLVM intermediate language assembly files. Else, it generates LLVM bit-code format object files (which may be passed on to the linker depending on the stage selection options). -flto is equivalent to -flto=full.
    • -flto=full [Default]
    • -flto=thin [Not supported, fall back to Full]
    • -flto=forcethin [Beta]
  • -m32
    Generates code for a 32-bit environment. The 32-bit environment sets int, long, and pointer to 32 bits and generates code that runs on any i386 system. The compiler generates x86 or IA32 32-bit ABI. The default on a 32-bit host is 32-bit ABI.
    Note: SUSE Linux Enterprise Server does not support the compilation of 32-bit applications from SP1. It only offers runtime support for the 32-bit binaries.
  • -m64

    Generates code for a 64-bit environment. The 64-bit environment sets int to 32 bits, long and pointer to 64 bits and generates code for the x86-64 architecture. The default on a 64-bit host is 64-bit ABI.

  • -ffast-math

    Enables a range of optimizations that provide faster, though sometimes less precise, mathematical operations that may not conform to the IEEE-754 specifications. When this option is specified, the __STDC_IEC_559__ macro is ignored even if set by the system headers.

  • -fopenmp

    Enables handling of the OpenMP directives and generates parallel code. The OpenMP library to be linked can be specified through the -fopenmp=<library> option.

    Note: If -fopenmp or -fopenmp=<library> (for example: -fopenmp=libomp or -fopenmp=libgomp) is specified, AOCC picks OpenMP library from the AOCC installed lib directory by default. To use an alternate version of the OpenMP library located at /path/to/lib/, use the following compilation command.
    • $ clang -fopenmp -I/path/to/include /path/to/lib/library test.c
    • $ clang -fopenmp=<library> -I/path/to/include /path/to/lib/library test.c

    While running the application, add /path/to/lib/ to your LD_LIBRARY_PATH using the following command.

    $ export LD_LIBRARY_PATH=/path/to/lib/:$LD_LIBRARY_PATH
  • -Os

    Similar to the level -O2 but with extra optimizations to reduce the code size.

  • -Oz

    Similar to the level -Os (and thus -O2) but reduces the code size further.

  • -O

    Equivalent to the level -O2.

  • -O4 and higher

    Equivalent to the level -O3.

  • -zopt

    Enables the subset of scalar, vector, and loop transformations including advanced variants of loop invariant code motion, SLP and loop vectorizations, loop-fusion, loop-interchange, loop-unswitch, loop tiling, and loop distribution.

  • -fPIC

    Enabled by default, this option generates Position Independent Code (PIC) for shared and static libraries. Use -fno-PIC to disable PIC generation.

  • -fPIE
    Enabled by default, this option generates PIC for executables and static libraries. Use -fno-PIE to disable PIC generation.
    Note: As -fPIC and -fPIE are default options since AOCC 4.1, location independent code is generated by default. With AOCC 4.1 or later, static libraries that are statically linked and not using -fPIC options so far must be rebuilt with AOCC with these default options. Else, it could display a linker error. Alternatively, use the options -fno-PIC/-fno-PIE with AOCC to disable generating location independent code.

Floating Point Options

  • -ffp-model

    Specifies floating point behavior of the compiler.

    Valid Values

    precise and fast

    where,
    • precise disables the optimizations that are not value-safe on floating-point data. FP contraction (FMA) is disabled.
    • fast behaves similar to specifying -ffast-math.

    This -ffp-model behavior is applicable only for AOCC Flang. For Clang, refer to the Clang floating point documentation.

    Usage

     -ffp-model={precise, fast}

Vector Optimization Options

  • -enable-strided-vectorization

    Enables strided memory vectorization as an enhancement to the interleaved vectorization framework present in LLVM. It enables the effective use of gather/scatter instruction patterns. Use this option along with the interleave vectorization option.

    Usage

    -mllvm -enable-strided-vectorization
  • -global-vectorize-slp={true,false}

    Vectorizes the straight-line code inside a basic block with data reordering vector operations. This option is set to false by default.

    Usage

    -mllvm -global-vectorize-slp={true,false}
  • -enable-loop-vectorization-with-conditions

    Enables efficient vectorization of loops with conditions by conditionally executing the vector instructions as opposed to flattening the loop body and vectorizing. The vectorized code uses vector versions of compare instructions to guard the instructions in the loop body and uses masked instructions to guard against unsafe memory operations. By default, this option is enabled under -O3.

    Usage

    -mllvm -enable-loop-vectorization-with-conditions
  • -legalize-vector-library-calls

    Splits the unsupported higher vector factor version of vector library calls into supported vector factor version of vector library calls for enabling vectorization. By default, this option is enabled under -O3.

    Usage

    -mllvm -legalize-vector-library-calls
  • -vectorize-non-contiguous-memory-aggressively

    Enables vectorization involving non-contiguous memory locations by generating multiple loads/stores and inserts. By default, this option is enabled under -O3.

    Usage

    -mllvm -vectorize-non-contiguous-memory-aggressively
  • -fvector-transform

    Enables the subset of vector transformations including improved variants of SLP and loop vectorization. It is enabled under -zopt.

    Usage

    -fvector-transform
  • -fepilog-vectorization-of-inductions

    Enables epilog vectorization of loops that require vectorization of loop induction variables.

    Usage

    -fepilog-vectorization-of-inductions
  • -fenable-restrict-based-lv

    Enables support for considering restrict qualifiers on local variables as non-alias in dependency analysis, which leads to enhanced loop vectorization opportunities.

    Usage

    -fenable-restrict-based-lv
  • -enable-conditional-fixed-value

    Enables vectorization for updating scalar values conditionally using a fixed constant.

    Usage

    -mllvm -enable-conditional-fixed-value

Loop Optimization Options

  • -enable-partial-unswitch

    Enables partial loop un-switching, which is an enhancement to the existing loop unswitching optimization in LLVM. Partial loop un-switching hoists a condition inside a loop from a path for which the execution condition remains invariant, whereas the original loop un-switching works for a condition that is completely loop invariant. The condition inside the loop gets hoisted out from the invariant path and original loop is retained for the path where condition is variant.

    Usage

    -mllvm -enable-partial-unswitch
  • -aggressive-loop-unswitch

    Enables a more aggressive loop unswitching heuristic, including implicit support for partial loop unswitching. It allows loops to be unswitched beyond the default cost threshold when a branch condition is reused multiple times within the loop, making the resulting code duplication worthwhile by eliminating redundant control flow.

    To limit code bloat, the heuristic favors branch conditions that appear frequently inside the loop. The aggressiveness is controlled by the following option, with the default value of 3.

    -mllvm -unswitch-identical-branches-min-count=<n>

    Usage

    -mllvm -aggressive-loop-unswitch -mllvm -unswitch-identical-branches-min-count=<n>

    where n is a positive integer and lower value of <n> facilitates more unswitching.

  • -lv-function-specialization

    Generates specialized function versions when the loops inside the function are vectorizable and the arguments are not aliased with each other.

    Usage

    -mllvm -lv-function-specialization
  • -loop-splitting

    Enables splitting of loops into multiple loops to eliminate the branches, which compare the loop induction with an invariant or constant expression. By default, this option is enabled under -O3. To disable this optimization, use

    -loop-splitting=false

    Usage

    -mllvm -loop-splitting
  • -enable-ipo-loop-split

    Enables splitting loops into multiple loops to eliminate branches, which compares the loop induction with a constant expression. This constant expression can be derived through inter-procedural analysis. By default, this option is enabled under -O3. To disable this optimization, use

    -enable-ipo-loop-split=false

    Usage

    -mllvm -enable-ipo-loop-split
  • -enable-loop-fusion

    Enables classical loop fusion transformation where the bodies of multiple loop nests are fused into one loop nest. The transformation checks various legality criteria involving the bounds of the loop nests involved, the control flow nesting of the loop nests, and so on. By default, the transformation is off but you can enable it by using this option. Loop fusion enables reuse of memory access operations across the loop nests and is also beneficial for cache performance. As part of the profitability check for this transformation, it uses code size thresholds which control the size of the fused loop body created.

    Usage

    -mllvm -enable-loop-fusion
  • -enable-loopinterchange

    Enables the classical loop interchange or loop permutation transformation on a loop nest. It reorders the loops in a multi-dimensional loop nest, checking for various legality criteria in the process. By default, the transformation is off but you can enable it by using this option. Loop interchange tries to find a reordering of the loops in a multi-dimensional loop nest such that the number of loop invariant expressions that may be hoisted out from an inner loop to a loop at a higher level may be maximized.

    Usage

    -mllvm -enable-loopinterchange
  • -fuse-tile-inner-loop

    Enables fusion of adjacent tiled loops as a part of loop tiling transformation. By default, this option is set to false.

    Usage

    -mllvm -fuse-tile-inner-loop
  • -enable-loop-distribute-adv

    Enables advanced loop distribution which improves loop vectorization by separating out the portions of the loop affecting vectorization. By default, this flag is disabled.

    Usage

    -mllvm -enable-loop-distribute-adv
  • -floop-transform

    Enables the subset of loop transformations including improved variants of loop-fusion, loop-interchange, loop blocking, and distribution. It is enabled under -zopt.

    Usage

    -floop-transform
  • -faggressive-loop-transform

    Enables the subset of loop transformations including improved variants of loop unswitching, loop-tiling, and loop versioning licm. It is enabled under -zopt.

    Usage

    -faggressive-loop-transform
  • -fstrip-mining

    Enables loop strip mining optimization. This optimization breaks a large loop into smaller segments or strips to improve temporal and spatial locality. This option should be invoked with -flto.

    Usage

    -flto -fstrip-mining
  • -ldist-scalar-expand

    Enables a feature of advanced loop distribution which distributes the loop with scalar expansion of non-affine accesses for better vectorization.

    Usage

    -Wl,-mllvm -Wl,-ldist-scalar-expand
  • -falign-loops

    Aligns the starting address of loops in the generated machine code to a specified boundary (example: 16, 32, 64 bytes).

    Usage

    -falign-loops=32

    The option -mllvm -align-loops is the opt, llc tool counterpart of -falign-loops which work for AMD Zen architectures only. This option takes the base 2 logarithm value of the preferred loop alignment for Zen architectures. The smallest possible alignment size is 2^3 = 8 bytes. Although values below 3 are allowed, they are not recommended.

  • -falign-functions

    Aligns the starting address of each function in the machine code to a specified byte boundary such as 16, 32, 64, or 128 bytes.

    Note: According to the SysV ABI for x86-64, the stack must be 16-byte aligned before executing a call instruction.

    Usage

    -falign-functions=32

    The option -mllvm -align-functions is the opt, llc tool counterpart of -falign-functions which work for AMD Zen architectures only. This option takes the base 2 logarithm value of the preferred function alignment for Zen architectures. The smallest possible alignment size is 2^3 = 8 bytes. Although values below 3 are allowed, they are not recommended.

Math Options

  • -convert-pow-exp-to-int={true,false}

    Converts the call to floating point exponent version of pow to its integer exponent version if the floating-point exponent can be converted to integer. This option is set to true by default.

    Usage

    -mllvm -convert-pow-exp-to-int={true, false}
  • -freciprocal-math

    Allows replacing division x/y by multiplication with the reciprocal x * (1/y), which may allow sharing the reciprocal (1/y) between multiple expressions. Unlike with -mrecip, no additional approximation is allowed when calculating the reciprocal (1/y). However, extra rounding errors will still occur compared to calculating x/y directly.

    Usage

    -freciprocal-math

Inline Optimization Options

  • -inline-recursion=[1,2,3,4]

    Enables inlining for recursive functions based on heuristics with level 4 being most aggressive. The default level will be 2. Higher levels may lead to code-bloat due to expansion of recursive functions at call sites.

    • For level 1-2: Enables inlining for recursive functions using heuristics with inline depth 1. Level 2 uses more aggressive heuristics.
    • For level 3: Enables inlining for all recursive functions with inline depth 1.
    • For level 4: Enables inlining for all recursive function with inline depth 10.

    This is more effective with -flto as the whole program analysis is required to perform this optimization.

    Usage

    -flto -finline-recursion=[1,2,3,4]
  • -mllvm -inline-threshold=<N>

    Sets the compiler’s inlining threshold to the specified value. This threshold guides the inliner’s heuristics in determining which functions to inline.

    Usage

    -mllvm -inline-threshold=1000
  • -extra-inliner

    Enables more aggressive inlining during the link time. When this option is enabled, the compiler becomes more aggressive in its inlining decisions, even beyond the default heuristics. This flag can be particularly useful in scenarios where performance is critical, and the cost of increased binary size is acceptable.

    Usage

    -Wl,-mllvm -Wl,-extra-inliner

Memory Layout Optimization Options

  • -fstruct-layout={1,2,3,4,5,6,7,8,9}

    Analyzes the whole program to determine if the structures in the code can be peeled, if dead or redundant fields can be deleted, and if the pointer or integer fields in the structure can be compressed. If feasible, this optimization transforms the code to enable these improvements. This transformation is likely to improve cache utilization and memory bandwidth. It is expected to improve the scalability of programs executed on multiple cores.

    This enables only under -flto as the whole program analysis is required to perform this optimization. You can choose different levels of aggressiveness with which this optimization can be applied to your application with 1 being the least aggressive and 7 being the most aggressive level.
    • -fstruct-layout=1 enables structure peeling.
    • -fstruct-layout=2 enables structure peeling and selectively compresses self-referential pointers in these structures to 32-bit pointers, wherever safe.
    • -fstruct-layout=3 enables structure peeling and selectively compresses self-referential pointers in these structures to 16-bit pointers, wherever safe.
    • -fstruct-layout=4 enables structure peeling, pointer compression as in level 2 and further enables compression of structure fields that are of 64-bit to 32-bit integer type. This is performed under a strict safety check.
    • -fstruct-layout=5 enables structure peeling, pointer compression as in level 3 and further enables compression of structure fields that are of 64-bit to 32-bit integer type. This is performed under a strict safety check.
    • -fstruct-layout=6 enables structure peeling, pointer compression as in level 2 and further enables compression of structure fields that are of 64-bit to 32-bit integer type. This is performed under a strict safety check.
    • -fstruct-layout=7 enables structure peeling, pointer compression as in level 3 and further enables compression of structure fields that are of 64-bit to 16-bit integer type.
    • -fstruct-layout=8 enables structure peeling, pointer compression, 64-bit integer type compression as in level 6 and creates optimal ordering of peeled structure fields that could improve runtime performance.
    • -fstruct-layout=9 enables structure peeling, pointer compression, 64-bit integer type compression as in level 7 and creates optimal ordering of peeled structure fields that could improve runtime performance.

    Usage

    -flto -fstruct-layout={1,2,3,4,5,6,7,8,9}
    Note:
    1. -fstruct-layout=4 and -fstruct-layout=5 are derived from -fstruct-layout=2 and -fstruct-layout=3 respectively, with the added feature of safe compression of 64-bit to 32-bit integer fields in structures. Going from -fstruct-layout=4 to -fstruct-layout=5 may result in higher performance if the pointer values are such that the pointers can be compressed to 16 bits.
    2. -fstruct-layout=6 and -fstruct-layout=7 are derived from -fstruct-layout=2 and -fstruct-layout=3 respectively, with the added feature of compression of 64-bit to 32-bit integer fields in structures. These are similar to -fstruct-layout=4 and -fstruct-layout=5, but here, the integer fields of the structures are always compressed from 64 bits to 32 bits, without any safety guarantee.
    3. This optimization is currently restricted to C/C++ inputs only. Also, avoid using this option when linking C/C++ objects with the Fortran objects.
  • -fremap-arrays

    Transforms the data layout of a single dimensional array to provide better cache locality. This optimization is effective only under -flto as the whole program analysis is required to perform this optimization, which can be invoked as -flto -fremap-arrays.

    Usage

    -flto -fremap-arrays
  • -reduce-array-computations={1,2,3}

    Performs array dataflow analysis and optimizes the unused array computations.

    • -reduce-array-computations=1: Eliminates the computations on unused array elements.
    • -reduce-array-computations=2: Eliminates the computations on zero valued array elements.
    • -reduce-array-computations=3: Eliminates the computations on unused and zero valued array elements (combination of 1 and 2).

    This optimization is effective with -flto as the whole program analysis is required to perform this optimization, which can be invoked as -flto -reduce-array-computations={1,2,3}.

    Usage

    -flto -mllvm -reduce-array-computations={1,2,3}

Instruction Level Optimization Options

  • -enable-X86-prefetching

    Enables the generation of x86 prefetch instruction for the memory references inside a loop/inside an inner most loop of a loop nest to prefetch the second dimension of multidimensional array/memory references in the inner most of a loop nest.

    Usage

    -mllvm -enable-X86-prefetching
  • -suppress-fmas

    Identifies the reduction patterns on FMA and suppresses the FMA generation as it is not profitable on the reduction patterns.

    Usage

    -mllvm -suppress-fmas
  • -fnt-store

    Generates a non-temporal store instruction for array accesses in a loop with a large trip count.

    Usage

    -fnt-store
  • -fnt-store=aggressive

    Generates non-temporal store instruction for array accesses in a loop, whose iteration count cannot be determined at compile time. In this case, compiler assumes the iteration count is huge.

    Usage

    -fnt-store=aggressive
  • -enable-redundant-movs

    Removes any redundant mov operations including redundant loads from memory and stores to memory. This can be invoked using -Wl,-plugin-opt=-enable-redundant-movs.

    Usage

    -Wl,-plugin-opt=-enable-redundant-movs
  • -merge-constant

    Attempts to promote frequently occurring constants to registers. The aim is to reduce the size of the instruction encoding for instructions using constants and obtain a performance improvement.

    Usage

    -mllvm -merge-constant
  • -mrecip={all,none,sqrt,vec-sqrt,'!'sqrt,'!'vec-sqrt,div,vec-div,'!'div,'!'vec-div}
    • -mrecip={all,none}

      Reciprocal instruction generations can be enabled/disabled by using all/none.

      Usage

      • -march=znver{4,5} -mrecip=all
      • -march=znver{4,5} -mrecip=none
    • -mrecip=sqrt,vec-sqrt

      Generates reciprocal square root instructions for float and double.

      Prefixing vec- generates reciprocal square root instructions for vector types. By default, this option is enabled under -march=znver{4,5}.

      Usage

      -march=znver{4,5} -mrecip=sqrt,vec-sqrt
    • -mrecip=div,vec-div

      Generates reciprocal division instruction for float and double.

      Prefixing vec- generates reciprocal division instruction for vector types.

      Usage

      -march=znver{4,5} -mrecip=div,vec-div
    • -mrecip='!'sqrt,'!'vec-sqrt,'!'div,'!'vec-div

      Prefixing ‘!’ prevents the generation of corresponding reciprocal instructions.

      Usage

      -march=znver{4,5} -mrecip='!'sqrt,'!'vec-sqrt,'!'div,'!'vec-div

    These approximate instructions are generated only when -funsafe-math-optimizations and

    -ffinite-math-only are enabled (which is implied by -ffast-math or -Ofast).

  • -optimize-strided-mem-cost

    Optimizes the cost model for strided access to memory.

    Usage

    -mllvm -optimize-strided-mem-cost
  • -fenable-aggressive-gather

    This option enables generation of gather instructions for cases where it is profitable.

    Usage

    -fenable-aggressive-gather

Scalar Optimization Options

  • -enable-licm-vrp

    Enables estimation of the virtual register pressure before performing loop invariant code motion. This estimation is used to control the number of loop invariants that will be hoisted during the loop invariant code motion.

    Usage

    -mllvm -enable-licm-vrp
  • -do-block-reorder={none,simple,complex,advanced}

    Enables reordering of control predicates based on cost to execute the expensive predicates less frequently.

    • none: Disables this optimization
    • simple: Reorders simple expressions (default)
    • complex: Reorders the control predicates involving exceptions
    • advanced: Reorders the control predicates involving exceptions by ensuring the memory safety of load operations in the reordered predicates

      Usage

      • -mllvm -do-block-reorder={none, simple, complex, advanced}
      • -Wl,-mllvm -Wl,-do-block-reorder={none, simple, complex, advanced}

      Limitation

      The advanced variant has dependency on amdalloc-ext library. Refer to amdalloc-ext in Linking AMD Library for more details. It is recommended you use amdalloc-ext alone as the allocator library for the advanced variant.

      Usage

      -Wl,-mllvm -Wl,-do-block-reorder=advanced -lamdalloc-ext

      amdalloc-ext Restriction

      Supported only in 64-bit mode on Linux platforms, this library is not thread-safe and so should not be used in any multi-threaded application.

  • -fscalar-transform

    Enables a subset of scalar transformations including improved variants of various code movement optimizations such as hoisting and invariant code motion. It is enabled under -zopt.

    Usage

    -fscalar-transform

Profile Guided Optimization Options

  • -fprofile-instr-generate

    Generate instrumented code to collect execution counts into <file> (overridden by LLVM_PROFILE_FILE environment variable).

  • -fprofile-instr-use=<profiled data file>

    Uses the profiling files generated from the program compiled with -fprofile-instr-generate to guide the optimization decisions.

    Usage
    • $clang -fprofile-instr-generate code.c -o code.out
      $LLVM_PROFILE_FILE=pfname.raw ./code.out
      $llvm-profdata merge -output=pfname.data pfname.raw
      $clang -fprofile-instr-use=pfname.data code.c -o code.out
    • $clang -fprofile-instr-generate=pfname.raw code.c -o code.out
      $./code.out
      $llvm-profdata merge -output=pfname.data pfname.raw
      $clang -fprofile-instr-use=pfname.data code.c -o code.out

Miscellaneous Options

  • -fitodcalls

    Promotes indirect to direct calls by placing conditional calls. Application or benchmarks that have small and deterministic set of target functions for function pointers that are passed as call parameters benefit from this optimization. Indirect-to-direct call promotion transforms the code to use all possible determined targets under runtime checks and falls back to the original code for all the other cases. Runtime checks are introduced by the compiler for each of these possible function pointer targets followed by direct calls to the targets.

    This is a link time optimization, which is invoked as -flto -fitodcalls.

    Usage

    -flto -fitodcalls
  • -fitodcallsbyclone

    Performs value specialization for functions with function pointers passed as an argument. It does this specialization by generating a clone of the function. The cloning of the function happens in the call chain as needed to allow conversion of indirect function call to direct call.

    This complements -fitodcalls optimization and is also a link time optimization, which is invoked as

    -flto -fitodcallsbyclone.

    Usage

    -flto -fitodcallsbyclone
  • -function-specialize

    Optimizes the functions with compile time constant formal arguments. This option is enabled by default under -O3.

    Usage

    -mllvm -function-specialize
  • -favoid-fpe-causing-opt

    Restricts a few optimizations that leads to floating point exceptions.

    Usage

    -favoid-fpe-causing-opt