Transforms
Pass builders
LLVM.NewPMPassBuilder — Type
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)
endFor 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)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.
Pass managers
LLVM.NewPMPassManager — Type
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())
endSee also: add!, NewPMPassBuilder
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!
Alias analyses
Custom passes
LLVM.NewPMCustomPass — Type
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!
LLVM.register! — Function
register!(pb, custom_pass)Register a custom pass with the pass builder. This is necessary before the pass can be used in a pass pipeline.
See also: NewPMModulePass, NewPMFunctionPass
Custom target info
LLVM.AbstractTargetTransformInfo — Type
abstract type AbstractTargetTransformInfoSubtype 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:
- Target-level knobs:
flat_address_space,has_branch_divergence,is_single_threaded. - Address-space predicates:
is_noop_addr_space_cast,is_valid_addr_space_cast,addrspaces_may_alias,can_have_non_undef_global_initializer_in_address_space. - Per-
Valuequeries:is_source_of_divergence,is_always_uniform,get_assumed_addr_space,get_predicated_addr_space. - Intrinsic hooks:
rewrite_intrinsic_with_address_space,collect_flat_address_operands.
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).
LLVM.flat_address_space — Function
flat_address_space(tti::AbstractTargetTransformInfo) -> UnsignedAddress 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.
LLVM.has_branch_divergence — Function
has_branch_divergence(tti::AbstractTargetTransformInfo) -> BoolWhether 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.
LLVM.is_single_threaded — Function
is_single_threaded(tti::AbstractTargetTransformInfo) -> BoolWhether 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).
LLVM.is_noop_addr_space_cast — Function
is_noop_addr_space_cast(tti::AbstractTargetTransformInfo,
from::Unsigned, to::Unsigned) -> BoolWhether an addrspacecast from from to to is a noop at runtime. If not defined, falls back to LLVM's baseline.
LLVM.is_valid_addr_space_cast — Function
is_valid_addr_space_cast(tti::AbstractTargetTransformInfo,
from::Unsigned, to::Unsigned) -> BoolWhether an addrspacecast from from to to is permitted. If not defined, falls back to LLVM's baseline.
LLVM.addrspaces_may_alias — Function
addrspaces_may_alias(tti::AbstractTargetTransformInfo,
as0::Unsigned, as1::Unsigned) -> BoolWhether pointers in address spaces as0 and as1 may alias. If not defined, falls back to LLVM's (conservative) baseline.
LLVM.can_have_non_undef_global_initializer_in_address_space — Function
can_have_non_undef_global_initializer_in_address_space(
tti::AbstractTargetTransformInfo, as::Unsigned) -> BoolWhether globals in address space as may have non-undef initializers. If not defined, falls back to LLVM's baseline (which consults DataLayout::isNonIntegralAddressSpace).
LLVM.is_source_of_divergence — Function
is_source_of_divergence(tti::AbstractTargetTransformInfo, v::Value) -> BoolWhether v is a source of divergence. Consulted by UniformityAnalysis. If not defined, falls back to LLVM's baseline.
LLVM.is_always_uniform — Function
is_always_uniform(tti::AbstractTargetTransformInfo, v::Value) -> BoolWhether v is known to hold the same value across all threads. Consulted by UniformityAnalysis. If not defined, falls back to LLVM's baseline.
LLVM.get_assumed_addr_space — Function
get_assumed_addr_space(tti::AbstractTargetTransformInfo, v::Value) -> UnsignedAddress space statically known to hold for v, or typemax(UInt) for "no assumption". If not defined, falls back to LLVM's baseline.
LLVM.get_predicated_addr_space — Function
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.
LLVM.rewrite_intrinsic_with_address_space — Function
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.
LLVM.collect_flat_address_operands — Function
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.
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.
LLVM.clone — Function
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.
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.
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.