[llvm] [LLVM][NewPM] Add C API for running the pipeline on a single function. (PR #103773)
Tim Besard via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 14 03:53:04 PDT 2024
https://github.com/maleadt created https://github.com/llvm/llvm-project/pull/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.
>From 55cc962d232d543a3012674b3068e9dfd690ad5b Mon Sep 17 00:00:00 2001
From: Tim Besard <tim.besard at gmail.com>
Date: Wed, 14 Aug 2024 12:51:49 +0200
Subject: [PATCH] [LLVM][NewPM] Add C API for running the pipeline on a single
function.
Also removes erroneous LLVMConsumeError from the pass builder tests
as the string conversion already consumes the error.
---
llvm/include/llvm-c/Transforms/PassBuilder.h | 10 ++++
llvm/lib/Passes/PassBuilderBindings.cpp | 52 +++++++++++++++----
.../PassBuilderBindingsTest.cpp | 16 +++++-
3 files changed, 66 insertions(+), 12 deletions(-)
diff --git a/llvm/include/llvm-c/Transforms/PassBuilder.h b/llvm/include/llvm-c/Transforms/PassBuilder.h
index 03a5abaa753312..a91cdb8e4e328f 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..e638a40dedc9d6 100644
--- a/llvm/lib/Passes/PassBuilderBindings.cpp
+++ b/llvm/lib/Passes/PassBuilderBindings.cpp
@@ -48,15 +48,24 @@ static TargetMachine *unwrap(LLVMTargetMachineRef P) {
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLVMPassBuilderOptions,
LLVMPassBuilderOptionsRef)
-LLVMErrorRef LLVMRunPasses(LLVMModuleRef M, const char *Passes,
- LLVMTargetMachineRef TM,
- LLVMPassBuilderOptionsRef Options) {
+LLVMErrorRef RunPasses(LLVMModuleRef M, LLVMValueRef F, const char *Passes,
+ LLVMTargetMachineRef TM,
+ LLVMPassBuilderOptionsRef Options) {
TargetMachine *Machine = unwrap(TM);
LLVMPassBuilderOptions *PassOpts = unwrap(Options);
bool Debug = PassOpts->DebugLogging;
bool VerifyEach = PassOpts->VerifyEach;
- Module *Mod = unwrap(M);
+ // Determine what to run passes on.
+ Module *Mod;
+ Function *Fun = nullptr;
+ if (F) {
+ Fun = unwrap<Function>(F);
+ Mod = Fun->getParent();
+ } else {
+ Mod = unwrap(M);
+ }
+
PassInstrumentationCallbacks PIC;
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC);
@@ -80,18 +89,39 @@ 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) {
+ return RunPasses(M, nullptr, Passes, TM, Options);
+}
+
+LLVMErrorRef LLVMRunPassesOnFunction(LLVMValueRef F, const char *Passes,
+ LLVMTargetMachineRef TM,
+ LLVMPassBuilderOptionsRef Options) {
+ return RunPasses(nullptr, F, Passes, TM, Options);
+}
+
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<O2>", 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);
+}
More information about the llvm-commits
mailing list