Skip to content

Commit

Permalink
[LLVM][NewPM] Add C API for running the pipeline on a single function. (
Browse files Browse the repository at this point in the history
llvm#103773)

By adding a new entrypoint, `LLVMRunPassesOnFunction`, as suggested in
https://discourse.llvm.org/t/newpm-c-api-questions/80598.

Also removes erroneous `LLVMConsumeError`s from the pass builder unit
tests as the string conversion already consumes the error, causing an
abort when the test would fail.
  • Loading branch information
maleadt authored Aug 19, 2024
1 parent 74a512d commit 00def06
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 14 deletions.
6 changes: 6 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ Changes to the C API
* ``LLVMGetNamedFunctionWithLength``
* ``LLVMGetNamedGlobalWithLength``

* The new pass manager can now be invoked with a custom alias analysis pipeline, using
the ``LLVMPassBuilderOptionsSetAAPipeline`` function.

* It is now also possible to run the new pass manager on a single function, by calling
``LLVMRunPassesOnFunction`` instead of ``LLVMRunPasses``.

Changes to the CodeGen infrastructure
-------------------------------------

Expand Down
10 changes: 10 additions & 0 deletions llvm/include/llvm-c/Transforms/PassBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@ LLVMErrorRef LLVMRunPasses(LLVMModuleRef M, const char *Passes,
LLVMTargetMachineRef TM,
LLVMPassBuilderOptionsRef Options);

/**
* Construct and run a set of passes over a function.
*
* This function behaves the same as LLVMRunPasses, but operates on a single
* function instead of an entire module.
*/
LLVMErrorRef LLVMRunPassesOnFunction(LLVMValueRef F, const char *Passes,
LLVMTargetMachineRef TM,
LLVMPassBuilderOptionsRef Options);

/**
* Create a new set of options for a PassBuilder
*
Expand Down
50 changes: 37 additions & 13 deletions llvm/lib/Passes/PassBuilderBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,12 @@ static TargetMachine *unwrap(LLVMTargetMachineRef P) {
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMPassBuilderOptions,
LLVMPassBuilderOptionsRef)

LLVMErrorRef LLVMRunPasses(LLVMModuleRef M, const char *Passes,
LLVMTargetMachineRef TM,
LLVMPassBuilderOptionsRef Options) {
TargetMachine *Machine = unwrap(TM);
LLVMPassBuilderOptions *PassOpts = unwrap(Options);
static LLVMErrorRef runPasses(Module *Mod, Function *Fun, const char *Passes,
TargetMachine *Machine,
LLVMPassBuilderOptions *PassOpts) {
bool Debug = PassOpts->DebugLogging;
bool VerifyEach = PassOpts->VerifyEach;

Module *Mod = unwrap(M);
PassInstrumentationCallbacks PIC;
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC);

Expand All @@ -80,18 +77,45 @@ LLVMErrorRef LLVMRunPasses(LLVMModuleRef M, const char *Passes,

StandardInstrumentations SI(Mod->getContext(), Debug, VerifyEach);
SI.registerCallbacks(PIC, &MAM);
ModulePassManager MPM;
if (VerifyEach) {
MPM.addPass(VerifierPass());
}
if (auto Err = PB.parsePassPipeline(MPM, Passes)) {
return wrap(std::move(Err));

// Run the pipeline.
if (Fun) {
FunctionPassManager FPM;
if (VerifyEach)
FPM.addPass(VerifierPass());
if (auto Err = PB.parsePassPipeline(FPM, Passes))
return wrap(std::move(Err));
FPM.run(*Fun, FAM);
} else {
ModulePassManager MPM;
if (VerifyEach)
MPM.addPass(VerifierPass());
if (auto Err = PB.parsePassPipeline(MPM, Passes))
return wrap(std::move(Err));
MPM.run(*Mod, MAM);
}

MPM.run(*Mod, MAM);
return LLVMErrorSuccess;
}

LLVMErrorRef LLVMRunPasses(LLVMModuleRef M, const char *Passes,
LLVMTargetMachineRef TM,
LLVMPassBuilderOptionsRef Options) {
TargetMachine *Machine = unwrap(TM);
LLVMPassBuilderOptions *PassOpts = unwrap(Options);
Module *Mod = unwrap(M);
return runPasses(Mod, nullptr, Passes, Machine, PassOpts);
}

LLVMErrorRef LLVMRunPassesOnFunction(LLVMValueRef F, const char *Passes,
LLVMTargetMachineRef TM,
LLVMPassBuilderOptionsRef Options) {
TargetMachine *Machine = unwrap(TM);
LLVMPassBuilderOptions *PassOpts = unwrap(Options);
Function *Fun = unwrap<Function>(F);
return runPasses(Fun->getParent(), Fun, Passes, Machine, PassOpts);
}

LLVMPassBuilderOptionsRef LLVMCreatePassBuilderOptions() {
return wrap(new LLVMPassBuilderOptions());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class PassBuilderCTest : public testing::Test {
LLVMDisposeMessage(Triple);
Context = LLVMContextCreate();
Module = LLVMModuleCreateWithNameInContext("test", Context);
LLVMTypeRef FT =
LLVMFunctionType(LLVMVoidTypeInContext(Context), nullptr, 0, 0);
Function = LLVMAddFunction(Module, "test", FT);
}

void TearDown() override {
Expand All @@ -52,6 +55,7 @@ class PassBuilderCTest : public testing::Test {
public:
LLVMTargetMachineRef TM;
LLVMModuleRef Module;
LLVMValueRef Function;
LLVMContextRef Context;
};

Expand All @@ -63,7 +67,6 @@ TEST_F(PassBuilderCTest, Basic) {
LLVMPassBuilderOptionsSetAAPipeline(Options, "basic-aa");
if (LLVMErrorRef E = LLVMRunPasses(Module, "default<O2>", TM, Options)) {
char *Msg = LLVMGetErrorMessage(E);
LLVMConsumeError(E);
LLVMDisposePassBuilderOptions(Options);
FAIL() << "Failed to run passes: " << Msg;
}
Expand All @@ -80,3 +83,14 @@ TEST_F(PassBuilderCTest, InvalidPassIsError) {
LLVMConsumeError(E2);
LLVMDisposePassBuilderOptions(Options);
}

TEST_F(PassBuilderCTest, Function) {
LLVMPassBuilderOptionsRef Options = LLVMCreatePassBuilderOptions();
if (LLVMErrorRef E =
LLVMRunPassesOnFunction(Function, "no-op-function", TM, Options)) {
char *Msg = LLVMGetErrorMessage(E);
LLVMDisposePassBuilderOptions(Options);
FAIL() << "Failed to run passes on function: " << Msg;
}
LLVMDisposePassBuilderOptions(Options);
}

0 comments on commit 00def06

Please sign in to comment.