Transforms

Pass builders

LLVM.NewPMPassBuilderType
NewPMPassBuilder(; verify_each=false, debug_logging=false, pipeline_tuning_kwargs...)

Create a new pass builder. The pass builder is the main object used to construct and run pass pipelines. The verify_each keyword argument enables module verification after each pass, while debug_logging can be used to enable more output. Pass builder objects needs to be disposed after use.

Several other keyword arguments can be used to tune the pipeline. This only has an effect when using one of LLVM's default pipelines, like default<O3>:

  • loop_interleaving::Bool=false: Enable loop interleaving.
  • loop_vectorization::Bool=false: Enable loop vectorization.
  • slp_vectorization::Bool=false: Enable SLP vectorization.
  • loop_unrolling::Bool=false: Enable loop unrolling.
  • forget_all_scev_in_loop_unroll::Bool=false: Forget all SCEV information in loop unrolling.
  • licm_mssa_opt_cap::Int=0: LICM MSSA optimization cap.
  • licm_mssa_no_acc_for_promotion_cap::Int=0: LICM MSSA no access for promotion cap.
  • call_graph_profile::Bool=false: Enable call graph profiling.
  • merge_functions::Bool=false: Enable function merging.

After a pass builder is constructed, custom passes can be registered with register!, passes or nested pass managers can be added with add!, and finally the passes can be run with run!:

@dispose pb = NewPMPassBuilder(verify_each=true) begin
    register!(pb, SomeCustomPass())
    add!(pb, SomeModulePass())
    add!(pb, NewPMFunctionPassManager()) do fpm
        add!(fpm, SomeFunctionPass())
    end
    run!(pb, mod, tm)
end

For quickly running a simple pass or pipeline, a shorthand run! method is provided that obviates the construction of a NewPMPassBuilder:

run!("some-pass", mod, tm; verify_each=true)

See also: register!, add!, run!

source
LLVM.run!Function
run!(pb::NewPMPassBuilder, mod::Module, [tm::TargetMachine])
run!(pipeline::String, mod::Module, [tm::TargetMachine])

Run passes on a module. The passes are specified by a pass builder or a string that represents a pass pipeline. The target machine is used to optimize the passes.

source

Pass managers

LLVM.NewPMPassManagerType
NewPMModulePassManager()
NewPMCGSCCPassManager()
NewPMFunctionPassManager()
NewPMLoopPassManager(; use_memory_ssa=false)
NewPMAAManager()

Create a new pass manager of the specified type. These objects can be used to construct pass pipelines, by add!ing passes to them, and finally add!ing them to a parent pass manager or pass builder.

Creating a pass manager and adding it to a parent manager or builder can be shortened using a single add!:

add!(parent, NewPMModulePassManager()) do mpm
    add!(mpm, SomeModulePass())
end

See also: add!, NewPMPassBuilder

source
LLVM.add!Function
add!(pm::AbstractPassManager, pass)

Adds a pass or pipeline to a pass builder or pass manager.

The pass or pipeline should be a string or string-convertible object known by LLVM. These can be constructed by using pass constructors, e.g., InternalizePass(), or by manually specifying names like default<O3>.

When using custom passes, remember that they need to be registered with the pass builder before they can be used.

See also: register!

source

Alias analyses

Custom passes

LLVM.NewPMCustomPassType
NewPMModulePass(name, callback)
NewPMFunctionPass(name, callback)

Create a new custom pass. The name is a string that will be used to identify the pass in the pass manager. The callback is a function that will be called when the pass is run. The function should take a single argument, the module or function to be processed, and return a boolean indicating whether the pass made any changes.

Before using a custom pass, it must be registered with a pass builder using register!.

See also: register!

source

Custom target info

LLVM.AbstractTargetTransformInfoType
abstract type AbstractTargetTransformInfo

Subtype this to supply a custom TargetTransformInfo to pass pipelines that would otherwise see only LLVM's conservative baseline.

Most LLVM back-ends (host CPU, NVPTX, AMDGPU) carry their own TTI through a TargetMachine; callers that already have one and pass it to run! don't need this. The feature is aimed at out-of-tree back-ends not linked into libLLVM (e.g. Metal) and at tooling that runs passes without a TargetMachine at all. In those pipelines, the baseline TTI reports no flat address space, no branch divergence, etc., and TTI-sensitive passes such as InferAddressSpacesPass or UniformityAnalysis silently no-op.

Subtypes override only the queries they care about; any query left un-overridden is handled by LLVM's TargetTransformInfoImplBase.

Attach an instance with target_transform_info!; attaching nothing reverts to LLVM's native TTI. When a TargetMachine is also supplied to run!, a custom TTI takes precedence.

Overridable queries:

source
LLVM.target_transform_info!Function
target_transform_info!(pb::NewPMPassBuilder, tti::AbstractTargetTransformInfo)
target_transform_info!(pb::NewPMPassBuilder, ::Nothing)

Attach an AbstractTargetTransformInfo subtype instance to the pass builder, replacing any previously-attached custom TTI. Pass nothing to revert to LLVM's native TTI (derived from the TargetMachine, if any; otherwise TargetTransformInfoImplBase with full DataLayout/Module-aware defaults).

source
LLVM.flat_address_spaceFunction
flat_address_space(tti::AbstractTargetTransformInfo) -> Unsigned

Address space the target treats as "flat" / generic. Required — alongside is_noop_addr_space_cast — for InferAddressSpacesPass to fold addrspacecasts. If not defined, LLVM reports no flat AS.

source
LLVM.has_branch_divergenceFunction
has_branch_divergence(tti::AbstractTargetTransformInfo) -> Bool

Whether the target can produce divergent control flow. Enables divergence-aware passes (SimplifyCFG, loop analyses) when true. If not defined, falls back to LLVM's baseline.

source
LLVM.is_single_threadedFunction
is_single_threaded(tti::AbstractTargetTransformInfo) -> Bool

Whether the target is single-threaded. A few passes skip concurrency-related transformations when true. If not defined, falls back to LLVM's baseline (which consults the module's "single-thread" flag).

source
LLVM.is_noop_addr_space_castFunction
is_noop_addr_space_cast(tti::AbstractTargetTransformInfo,
                        from::Unsigned, to::Unsigned) -> Bool

Whether an addrspacecast from from to to is a noop at runtime. If not defined, falls back to LLVM's baseline.

source
LLVM.is_valid_addr_space_castFunction
is_valid_addr_space_cast(tti::AbstractTargetTransformInfo,
                         from::Unsigned, to::Unsigned) -> Bool

Whether an addrspacecast from from to to is permitted. If not defined, falls back to LLVM's baseline.

source
LLVM.addrspaces_may_aliasFunction
addrspaces_may_alias(tti::AbstractTargetTransformInfo,
                     as0::Unsigned, as1::Unsigned) -> Bool

Whether pointers in address spaces as0 and as1 may alias. If not defined, falls back to LLVM's (conservative) baseline.

source
LLVM.can_have_non_undef_global_initializer_in_address_spaceFunction
can_have_non_undef_global_initializer_in_address_space(
    tti::AbstractTargetTransformInfo, as::Unsigned) -> Bool

Whether globals in address space as may have non-undef initializers. If not defined, falls back to LLVM's baseline (which consults DataLayout::isNonIntegralAddressSpace).

source
LLVM.is_source_of_divergenceFunction
is_source_of_divergence(tti::AbstractTargetTransformInfo, v::Value) -> Bool

Whether v is a source of divergence. Consulted by UniformityAnalysis. If not defined, falls back to LLVM's baseline.

source
LLVM.is_always_uniformFunction
is_always_uniform(tti::AbstractTargetTransformInfo, v::Value) -> Bool

Whether v is known to hold the same value across all threads. Consulted by UniformityAnalysis. If not defined, falls back to LLVM's baseline.

source
LLVM.get_assumed_addr_spaceFunction
get_assumed_addr_space(tti::AbstractTargetTransformInfo, v::Value) -> Unsigned

Address space statically known to hold for v, or typemax(UInt) for "no assumption". If not defined, falls back to LLVM's baseline.

source
LLVM.get_predicated_addr_spaceFunction
get_predicated_addr_space(tti::AbstractTargetTransformInfo, v::Value)
    -> (predicate::Union{Value,Nothing}, as::Unsigned)

Address space that holds for v when predicate is true. Return (nothing, typemax(UInt)) for "no inference". If not defined, falls back to LLVM's baseline.

source
LLVM.rewrite_intrinsic_with_address_spaceFunction
rewrite_intrinsic_with_address_space(tti::AbstractTargetTransformInfo,
    ii::Value, old::Value, new::Value) -> Union{Value,Nothing}

Rewrite an intrinsic call ii after its pointer operand old has been replaced by new (in a different address space). Return the rewritten value, or nothing to keep the existing call. If not defined, falls back to LLVM's baseline.

source
LLVM.collect_flat_address_operandsFunction
collect_flat_address_operands(tti::AbstractTargetTransformInfo, iid::Unsigned)
    -> Vector{Int}

Operand indices of intrinsic iid that are flat-address-space pointer operands. Capped at 32 entries by the underlying C API. If not defined, falls back to LLVM's baseline.

source

IR cloning

LLVM.clone_into!Function
clone_into!(new::LLVM.Function, old::LLVM.Function; [suffix::String],
            [value_map::Dict{<:Value,<:Value}],
            [changes::LLVM.LLVMCloneFunctionChangeType],
            [type_mapper::Function],
            [materializer::Function])

Clone the contents of a function old into a new function new. The value_map dictionary can be used to remap values from the old function to the new function, while suffix appends a suffix to all values cloned. The type_mapper and materializer functions can be used to respectively map types and materialize values on demand.

The changes argument determines how this function behaves; refer to the LLVM documentation of CloneFunctionInto for more details.

source
LLVM.cloneFunction
clone(f::Function; [value_map::Dict{Value,Value}])

Simpler version of clone_into! that clones a function f into a new function, optionally mapping values according to the value_map dictionary.

source
clone(bb::BasicBlock]; dest=parent(bb), [suffix::String], [value_map::Dict{Value,Value}])

Clone a basic block bb by copying all instructions. The new block is inserted at the end of the parent function; this can be altered by setting dest to a different function, or to nothing to create a detached block. The suffix is appended to the name of the cloned basic block.

Warn

This function only remaps values that are defined in the cloned basic block. Values defined outside the basic block (e.g. function arguments) are not remapped by default. This means that the cloned basic block can generally only be used within the same function that it was cloned from, unless you manually remap other values. This can be done passing a value_map dictionary.

source