From 00def06c6e9a0582e85bef5f3a186839c48d1ae2 Mon Sep 17 00:00:00 2001 From: Tim Besard Date: Mon, 19 Aug 2024 12:34:23 +0200 Subject: [PATCH] [LLVM][NewPM] Add C API for running the pipeline on a single function. (#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. --- llvm/docs/ReleaseNotes.rst | 6 +++ llvm/include/llvm-c/Transforms/PassBuilder.h | 10 ++++ llvm/lib/Passes/PassBuilderBindings.cpp | 50 ++++++++++++++----- .../PassBuilderBindingsTest.cpp | 16 +++++- 4 files changed, 68 insertions(+), 14 deletions(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 057bd5345fba28..d40bb2682f9ad8 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -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 ------------------------------------- diff --git a/llvm/include/llvm-c/Transforms/PassBuilder.h b/llvm/include/llvm-c/Transforms/PassBuilder.h index 03a5abaa753312..d297b57cadd07d 100644 --- a/llvm/include/llvm-c/Transforms/PassBuilder.h +++ b/llvm/include/llvm-c/Transforms/PassBuilder.h @@ -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 * diff --git a/llvm/lib/Passes/PassBuilderBindings.cpp b/llvm/lib/Passes/PassBuilderBindings.cpp index 4e12dd2226c4d2..933fe89e53a94c 100644 --- a/llvm/lib/Passes/PassBuilderBindings.cpp +++ b/llvm/lib/Passes/PassBuilderBindings.cpp @@ -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); @@ -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(F); + return runPasses(Fun->getParent(), Fun, Passes, Machine, PassOpts); +} + LLVMPassBuilderOptionsRef LLVMCreatePassBuilderOptions() { return wrap(new LLVMPassBuilderOptions()); } diff --git a/llvm/unittests/Passes/PassBuilderBindings/PassBuilderBindingsTest.cpp b/llvm/unittests/Passes/PassBuilderBindings/PassBuilderBindingsTest.cpp index 2b06033f0c3fa2..4e17b1ad09e2b3 100644 --- a/llvm/unittests/Passes/PassBuilderBindings/PassBuilderBindingsTest.cpp +++ b/llvm/unittests/Passes/PassBuilderBindings/PassBuilderBindingsTest.cpp @@ -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 { @@ -52,6 +55,7 @@ class PassBuilderCTest : public testing::Test { public: LLVMTargetMachineRef TM; LLVMModuleRef Module; + LLVMValueRef Function; LLVMContextRef Context; }; @@ -63,7 +67,6 @@ TEST_F(PassBuilderCTest, Basic) { LLVMPassBuilderOptionsSetAAPipeline(Options, "basic-aa"); if (LLVMErrorRef E = LLVMRunPasses(Module, "default", TM, Options)) { char *Msg = LLVMGetErrorMessage(E); - LLVMConsumeError(E); LLVMDisposePassBuilderOptions(Options); FAIL() << "Failed to run passes: " << Msg; } @@ -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); +}