Skip to content

Commit

Permalink
Add support for specifying the AA pipeline.
Browse files Browse the repository at this point in the history
  • Loading branch information
maleadt committed Aug 14, 2024
1 parent 7f4b740 commit 8fe5125
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 20 deletions.
5 changes: 1 addition & 4 deletions deps/LLVMExtra/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@

cmake_minimum_required(VERSION 3.3)
cmake_minimum_required(VERSION 3.13.4)

SET(CMAKE_CXX_FLAGS "-Wall -fPIC -fno-rtti")
cmake_policy(SET CMP0074 NEW)
cmake_policy(SET CMP0077 NEW)

project(LLVMExtra
VERSION
Expand Down
2 changes: 2 additions & 0 deletions deps/LLVMExtra/include/LLVMExtra.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,8 @@ void LLVMPassBuilderExtensionsRegisterFunctionPass(LLVMPassBuilderExtensionsRef
const char *PassName,
LLVMJuliaFunctionPassCallback Callback,
void *Thunk);
void LLVMPassBuilderExtensionsSetAAPipeline(LLVMPassBuilderExtensionsRef Extensions,
const char *AAPipeline);
LLVMErrorRef LLVMRunJuliaPasses(LLVMModuleRef M, const char *Passes,
LLVMTargetMachineRef TM, LLVMPassBuilderOptionsRef Options,
LLVMPassBuilderExtensionsRef Extensions);
Expand Down
54 changes: 44 additions & 10 deletions deps/LLVMExtra/lib/NewPM.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "LLVMExtra.h"

#include <llvm/Analysis/AliasAnalysis.h>
#include <llvm/IR/Verifier.h>
#include <llvm/Passes/PassBuilder.h>
#include <llvm/Passes/StandardInstrumentations.h>
Expand All @@ -18,19 +19,24 @@ namespace llvm {
// Keep this in sync with PassBuilderBindings.cpp!
class LLVMPassBuilderOptions {
public:
explicit LLVMPassBuilderOptions(bool DebugLogging = false, bool VerifyEach = false,
PipelineTuningOptions PTO = PipelineTuningOptions())
: DebugLogging(DebugLogging), VerifyEach(VerifyEach), PTO(PTO) {}

bool DebugLogging;
bool VerifyEach;
#if LLVM_VERSION_MAJOR >= 20
const char *AAPipeline;
#endif
PipelineTuningOptions PTO;
};
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMPassBuilderOptions, LLVMPassBuilderOptionsRef)

class LLVMPassBuilderExtensions {
public:
// A callback to register additional pipeline parsing callbacks with the pass builder.
// This is used to support Julia's passes.
void (*RegistrationCallback)(void *);

// A list of callbacks that each register a single custom module or function pass.
// These callbacks are generated here in C++, and match against a pass name.
// This is used to enable custom LLVM passes implemented in Julia.
SmallVector<std::function<bool(StringRef, ModulePassManager &,
ArrayRef<PassBuilder::PipelineElement>)>,
2>
Expand All @@ -39,6 +45,11 @@ class LLVMPassBuilderExtensions {
ArrayRef<PassBuilder::PipelineElement>)>,
2>
FunctionPipelineParsingCallbacks;

#if LLVM_VERSION_MAJOR < 20
// A pipeline describing the alias analysis passes to run.
const char *AAPipeline;
#endif
};
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMPassBuilderExtensions, LLVMPassBuilderExtensionsRef)
} // namespace llvm
Expand Down Expand Up @@ -120,6 +131,17 @@ void LLVMPassBuilderExtensionsRegisterFunctionPass(LLVMPassBuilderExtensionsRef
return;
}

// Alias analysis pipeline (back-port of llvm/llvm-project#102482)

#if LLVM_VERSION_MAJOR < 20
void LLVMPassBuilderExtensionsSetAAPipeline(LLVMPassBuilderExtensionsRef Extensions,
const char *AAPipeline) {
LLVMPassBuilderExtensions *PassExts = unwrap(Extensions);
PassExts->AAPipeline = AAPipeline;
return;
}
#endif


// Vendored API entrypoint

Expand All @@ -139,20 +161,32 @@ LLVMErrorRef LLVMRunJuliaPasses(LLVMModuleRef M, const char *Passes,
#else
PassBuilder PB(Machine, PassOpts->PTO, None, &PIC);
#endif
if (PassExts->RegistrationCallback) {
if (PassExts->RegistrationCallback)
PassExts->RegistrationCallback(&PB);
}
for (auto &Callback : PassExts->ModulePipelineParsingCallbacks) {
for (auto &Callback : PassExts->ModulePipelineParsingCallbacks)
PB.registerPipelineParsingCallback(Callback);
}
for (auto &Callback : PassExts->FunctionPipelineParsingCallbacks) {
for (auto &Callback : PassExts->FunctionPipelineParsingCallbacks)
PB.registerPipelineParsingCallback(Callback);
}

LoopAnalysisManager LAM;
FunctionAnalysisManager FAM;
CGSCCAnalysisManager CGAM;
ModuleAnalysisManager MAM;
const char *AAPipeline =
#if LLVM_VERSION_MAJOR >= 20
PassOpts->AAPipeline;
#else
PassExts->AAPipeline;
#endif
if (AAPipeline) {
// If we have a custom AA pipeline, we need to register it _before_ calling
// registerFunctionAnalyses, or the default alias analysis pipeline is used.
AAManager AA;
if (auto Err = PB.parseAAPipeline(AA, AAPipeline)) {
return wrap(std::move(Err));
}
FAM.registerPass([&] { return std::move(AA); });
}
PB.registerLoopAnalyses(LAM);
PB.registerFunctionAnalyses(FAM);
PB.registerCGSCCAnalyses(CGAM);
Expand Down
4 changes: 4 additions & 0 deletions lib/15/libLLVM_extra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,10 @@ function LLVMPassBuilderExtensionsRegisterFunctionPass(Options, PassName, Callba
ccall((:LLVMPassBuilderExtensionsRegisterFunctionPass, libLLVMExtra), Cvoid, (LLVMPassBuilderExtensionsRef, Cstring, LLVMJuliaFunctionPassCallback, Ptr{Cvoid}), Options, PassName, Callback, Thunk)
end

function LLVMPassBuilderExtensionsSetAAPipeline(Extensions, AAPipeline)
ccall((:LLVMPassBuilderExtensionsSetAAPipeline, libLLVMExtra), Cvoid, (LLVMPassBuilderExtensionsRef, Cstring), Extensions, AAPipeline)
end

function LLVMRunJuliaPasses(M, Passes, TM, Options, Extensions)
ccall((:LLVMRunJuliaPasses, libLLVMExtra), LLVMErrorRef, (LLVMModuleRef, Cstring, LLVMTargetMachineRef, LLVMPassBuilderOptionsRef, LLVMPassBuilderExtensionsRef), M, Passes, TM, Options, Extensions)
end
Expand Down
4 changes: 4 additions & 0 deletions lib/16/libLLVM_extra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,10 @@ function LLVMPassBuilderExtensionsRegisterFunctionPass(Options, PassName, Callba
ccall((:LLVMPassBuilderExtensionsRegisterFunctionPass, libLLVMExtra), Cvoid, (LLVMPassBuilderExtensionsRef, Cstring, LLVMJuliaFunctionPassCallback, Ptr{Cvoid}), Options, PassName, Callback, Thunk)
end

function LLVMPassBuilderExtensionsSetAAPipeline(Extensions, AAPipeline)
ccall((:LLVMPassBuilderExtensionsSetAAPipeline, libLLVMExtra), Cvoid, (LLVMPassBuilderExtensionsRef, Cstring), Extensions, AAPipeline)
end

function LLVMRunJuliaPasses(M, Passes, TM, Options, Extensions)
ccall((:LLVMRunJuliaPasses, libLLVMExtra), LLVMErrorRef, (LLVMModuleRef, Cstring, LLVMTargetMachineRef, LLVMPassBuilderOptionsRef, LLVMPassBuilderExtensionsRef), M, Passes, TM, Options, Extensions)
end
Expand Down
4 changes: 4 additions & 0 deletions lib/17/libLLVM_extra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,10 @@ function LLVMPassBuilderExtensionsRegisterFunctionPass(Options, PassName, Callba
ccall((:LLVMPassBuilderExtensionsRegisterFunctionPass, libLLVMExtra), Cvoid, (LLVMPassBuilderExtensionsRef, Cstring, LLVMJuliaFunctionPassCallback, Ptr{Cvoid}), Options, PassName, Callback, Thunk)
end

function LLVMPassBuilderExtensionsSetAAPipeline(Extensions, AAPipeline)
ccall((:LLVMPassBuilderExtensionsSetAAPipeline, libLLVMExtra), Cvoid, (LLVMPassBuilderExtensionsRef, Cstring), Extensions, AAPipeline)
end

function LLVMRunJuliaPasses(M, Passes, TM, Options, Extensions)
ccall((:LLVMRunJuliaPasses, libLLVMExtra), LLVMErrorRef, (LLVMModuleRef, Cstring, LLVMTargetMachineRef, LLVMPassBuilderOptionsRef, LLVMPassBuilderExtensionsRef), M, Passes, TM, Options, Extensions)
end
Expand Down
4 changes: 4 additions & 0 deletions lib/18/libLLVM_extra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@ function LLVMPassBuilderExtensionsRegisterFunctionPass(Options, PassName, Callba
ccall((:LLVMPassBuilderExtensionsRegisterFunctionPass, libLLVMExtra), Cvoid, (LLVMPassBuilderExtensionsRef, Cstring, LLVMJuliaFunctionPassCallback, Ptr{Cvoid}), Options, PassName, Callback, Thunk)
end

function LLVMPassBuilderExtensionsSetAAPipeline(Extensions, AAPipeline)
ccall((:LLVMPassBuilderExtensionsSetAAPipeline, libLLVMExtra), Cvoid, (LLVMPassBuilderExtensionsRef, Cstring), Extensions, AAPipeline)
end

function LLVMRunJuliaPasses(M, Passes, TM, Options, Extensions)
ccall((:LLVMRunJuliaPasses, libLLVMExtra), LLVMErrorRef, (LLVMModuleRef, Cstring, LLVMTargetMachineRef, LLVMPassBuilderOptionsRef, LLVMPassBuilderExtensionsRef), M, Passes, TM, Options, Extensions)
end
Expand Down
46 changes: 42 additions & 4 deletions src/newpm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

## pass managers

export NewPMModulePassManager, NewPMCGSCCPassManager, NewPMFunctionPassManager, NewPMLoopPassManager
export NewPMModulePassManager, NewPMCGSCCPassManager, NewPMFunctionPassManager,
NewPMLoopPassManager, NewPMAAManager

abstract type AbstractPassManager end

Expand Down Expand Up @@ -174,6 +175,7 @@ mutable struct NewPMPassBuilder <: AbstractPassManager
opts::API.LLVMPassBuilderOptionsRef
exts::API.LLVMPassBuilderExtensionsRef
passes::Vector{String}
aa_passes::Vector{String}
custom_passes::Vector{NewPMCustomPass}
end

Expand All @@ -185,7 +187,7 @@ Base.unsafe_convert(::Type{API.LLVMPassBuilderOptionsRef}, pb::NewPMPassBuilder)
function NewPMPassBuilder(; kwargs...)
opts = API.LLVMCreatePassBuilderOptions()
exts = API.LLVMCreatePassBuilderExtensions()
obj = mark_alloc(NewPMPassBuilder(opts, exts, [], []))
obj = mark_alloc(NewPMPassBuilder(opts, exts, [], [], []))

for (name, value) in pairs(kwargs)
if name == :verify_each
Expand Down Expand Up @@ -247,13 +249,15 @@ run!

function run!(pb::NewPMPassBuilder, mod::Module, tm::Union{Nothing,TargetMachine}=nothing)
isempty(pb.passes) && return
pipeline = join(pb.passes, ",")
aa_pipeline = join(pb.aa_passes, ",")

# XXX: The Base API is too restricted, not supporting custom passes
# or Julia's pass registration callback
#@check API.LLVMRunPasses(mod, string(pb), tm, pb.opts)

thunks = Vector{Any}(undef, length(pb.custom_passes))
GC.@preserve thunks begin
GC.@preserve thunks aa_pipeline begin
# register custom passes
for (i,pass) in enumerate(pb.custom_passes)
if pass.type === :module
Expand All @@ -273,7 +277,16 @@ function run!(pb::NewPMPassBuilder, mod::Module, tm::Union{Nothing,TargetMachine
julia_callback = cglobal(:jl_register_passbuilder_callbacks)
API.LLVMPassBuilderExtensionsSetRegistrationCallback(pb.exts, julia_callback)

@check API.LLVMRunJuliaPasses(mod, string(pb), something(tm, C_NULL),
# register AA pipeline
if !isempty(aa_pipeline)
if version() >= v"20"
API.LLVMPassBuilderOptionsSetAAPipeline(pb.opts, aa_pipeline)
else
API.LLVMPassBuilderExtensionsSetAAPipeline(pb.exts, aa_pipeline)
end
end

@check API.LLVMRunJuliaPasses(mod, pipeline, something(tm, C_NULL),
pb.opts, pb.exts)
end
end
Expand Down Expand Up @@ -863,3 +876,28 @@ Base.string(options::LICMPassOptions) =
@loop_pass "licm" LICMPass LICMPassOptions

@loop_pass "lnicm" LNICMPass LICMPassOptions


## alias analyses

struct NewPMAAManager <: AbstractPassManager
passes::Vector{String}

NewPMAAManager() = new([])
end

Base.string(pb::NewPMAAManager) = join(pb.passes, ",")

add!(pb::NewPMPassBuilder, aa::NewPMAAManager) = push!(pb.aa_passes, string(aa))
add!(pm::NewPMAAManager, aa::NewPMAAManager) =
error("Alias analyses can only be added to the top-level pass builder")

macro aa_pass(pass_name, class_name, params=nothing)
define_pass(pass_name, class_name, params)
end

@aa_pass "basic-aa" BasicAA
@aa_pass "objc-arc-aa" ObjCARCAA
@aa_pass "scev-aa" SCEVAA
@aa_pass "scoped-noalias-aa" ScopedNoAliasAA
@aa_pass "tbaa" TypeBasedAA
1 change: 1 addition & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[deps]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
BFloat16s = "ab4f0b2a-ad5b-11e8-123f-65d77653426b"
IOCapture = "b5f81e59-6552-4d32-b1f0-c071b021bf89"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
ReTestItems = "817f1d60-ba6b-4fd5-9520-3cf149f6a823"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
45 changes: 43 additions & 2 deletions test/newpm_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
@testitem "newpm" begin

using LLVM.Interop
using IOCapture

function test_module()
mod = LLVM.Module("test")
Expand All @@ -19,7 +20,7 @@ function test_module()
end

@testset "pass builder" begin
@dispose ctx=Context() pb=NewPMPassBuilder() begin
@dispose ctx=Context() begin
# single pass
@dispose mod=test_module() begin
# by string
Expand Down Expand Up @@ -74,7 +75,7 @@ end
end

@testset "pass manager" begin
@dispose ctx=Context() pb=NewPMPassBuilder() begin
@dispose ctx=Context() begin
# pass manager interface
@dispose pb=NewPMPassBuilder() mod=test_module() begin
add!(pb, "no-op-module")
Expand Down Expand Up @@ -364,4 +365,44 @@ end
end
end

@testset "alias analyses" begin
# default pipeline
@dispose ctx=Context() pb=NewPMPassBuilder() begin
@dispose pb=NewPMPassBuilder(;debug_logging=true) mod=test_module() begin
add!(pb, "aa-eval")

io = IOCapture.capture() do
run!(pb, mod)
end

@test contains(io.output, "Running analysis: BasicAA")
@test contains(io.output, "Running analysis: TypeBasedAA")
@test contains(io.output, "Running analysis: ScopedNoAliasAA")
end
end

# custom pipeline
@dispose ctx=Context() pb=NewPMPassBuilder() begin
@dispose pb=NewPMPassBuilder(;debug_logging=true) mod=test_module() begin
add!(pb, NewPMAAManager()) do aa
# by string
add!(aa, "basic-aa")

# by object
add!(aa, SCEVAA())
end
add!(pb, "aa-eval")

io = IOCapture.capture() do
run!(pb, mod)
end

@test contains(io.output, "Running analysis: BasicAA")
@test contains(io.output, "Running analysis: SCEVAA")
@test !contains(io.output, "Running analysis: TypeBasedAA")
@test !contains(io.output, "Running analysis: ScopedNoAliasAA")
end
end
end

end

0 comments on commit 8fe5125

Please sign in to comment.