[clang] [llvm] [CodeGen] Expose the extensibility of PassConfig to plugins (PR #139059)

2025-05-21 Thread Matt Arsenault via cfe-commits

arsenm wrote:

> I don't think you can reasonably test this with a lit test, you have to add 
> this as a proper build target in llvm/examples similar to Bye.

A lit test could then drive the load of that plugin, but the lit test can't 
contain the pass itself 

https://github.com/llvm/llvm-project/pull/139059
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [CodeGen] Expose the extensibility of PassConfig to plugins (PR #139059)

2025-05-21 Thread Matt Arsenault via cfe-commits

arsenm wrote:

I don't think you can reasonably test this with a lit test, you have to add 
this as a proper build target in llvm/examples similar to Bye 

https://github.com/llvm/llvm-project/pull/139059
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [CodeGen] Expose the extensibility of PassConfig to plugins (PR #139059)

2025-05-20 Thread via cfe-commits

Tcc100 wrote:

I added a test case and some docs, which tuned out to be more challenging than 
expected, since I couldn't find any test case for the plugin system. The lit 
test in this PR requires the current llvm headers, which are not provided by 
the lit system, thus, it currently only works if you provide the absolute path 
in your system. I'd appreciate any pointers on how to implement this correctly.

https://github.com/llvm/llvm-project/pull/139059
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [CodeGen] Expose the extensibility of PassConfig to plugins (PR #139059)

2025-05-20 Thread via cfe-commits


@@ -72,6 +74,10 @@ namespace yaml {
 struct MachineFunctionInfo;
 } // namespace yaml
 
+class TargetMachine;
+using PassConfigCallback =
+std::function;

Tcc100 wrote:

I think this should be a owning reference, similar to the other callback 
vectors.

https://github.com/llvm/llvm-project/pull/139059
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [CodeGen] Expose the extensibility of PassConfig to plugins (PR #139059)

2025-05-20 Thread via cfe-commits


@@ -119,6 +119,9 @@ addPassesToGenerateCode(CodeGenTargetMachineImpl &TM, 
PassManagerBase &PM,
   PM.add(PassConfig);
   PM.add(&MMIWP);
 
+  for (auto& C : *TargetMachine::TargetPassConfigCallbacks)

Tcc100 wrote:

This is same syntax as most of the callbacks in the code base use. Do you think 
not using auto would be better in this case?

https://github.com/llvm/llvm-project/pull/139059
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [CodeGen] Expose the extensibility of PassConfig to plugins (PR #139059)

2025-05-20 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: None (Tcc100)


Changes

This PR exposes the backend pass config to plugins via a callback. Plugin 
authors can register a callback that is being triggered before the target 
backend adds their passes to the pipeline. In the callback they then get access 
to the `TargetMachine`, the `PassManager`, and the `TargetPassConfig`. This 
allows plugins to call `TargetPassConfig::insertPass`, which is honored in the 
subsequent `addPass` of the main backend. We implemented this using the legacy 
pass manager as the backend is still using the old pass manager.

The following example shows how plugin authors can use the callback. Since its 
a callback that is not doing anything without anybody registering it, there 
shouldn't be any potential harm to the compiler unless a plugin is present.

```cpp
__attribute__((constructor)) static void initCodeGenPlugin() {
initializeCodeGenTestPass(*PassRegistry::getPassRegistry());

TargetMachine::registerTargetPassConfigCallback([](auto &TM, auto 
&PM, auto *TPC) {
TPC->insertPass(&GCLoweringID, &CodeGenTest::ID);
});
}
```

---
Full diff: https://github.com/llvm/llvm-project/pull/139059.diff


5 Files Affected:

- (added) clang/test/CodeGen/passconfighook.cpp (+56) 
- (modified) llvm/docs/WritingAnLLVMPass.rst (+17) 
- (modified) llvm/include/llvm/Target/TargetMachine.h (+14) 
- (modified) llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp (+3) 
- (modified) llvm/lib/Target/TargetMachine.cpp (+3) 


``diff
diff --git a/clang/test/CodeGen/passconfighook.cpp 
b/clang/test/CodeGen/passconfighook.cpp
new file mode 100644
index 0..094df123f3de1
--- /dev/null
+++ b/clang/test/CodeGen/passconfighook.cpp
@@ -0,0 +1,56 @@
+// RUN: %clangxx -shared -fPIC -I??/install/include -L%llvmshlibdir %s -o %t.so
+// RUN: %clangxx -O3 -DMAIN -Xclang -load -Xclang %t.so %s -o %t-main | 
FileCheck %s
+
+#ifndef MAIN
+
+#include 
+#include 
+#include 
+#include 
+
+#define DEBUG_TYPE "codegen-test"
+#define CODEGEN_TEST_NAME "CodeGen Test Pass"
+
+using namespace llvm;
+
+namespace llvm {
+void initializeCodeGenTestPass(PassRegistry &);
+} // namespace llvm
+
+class CodeGenTest : public MachineFunctionPass {
+public:
+static char ID;
+
+CodeGenTest(): MachineFunctionPass(ID) {
+}
+
+bool runOnMachineFunction(MachineFunction &MF) override {
+outs() << "[CodeGen] CodeGenTest::runOnMachineFunction" << "\n";
+return true;
+}
+
+StringRef getPassName() const override {
+return CODEGEN_TEST_NAME;
+}
+};
+
+char CodeGenTest::ID = 0;
+INITIALIZE_PASS(CodeGenTest, DEBUG_TYPE, CODEGEN_TEST_NAME, false, false)
+
+__attribute__((constructor)) static void initCodeGenPlugin() {
+initializeCodeGenTestPass(*PassRegistry::getPassRegistry());
+
+TargetMachine::registerTargetPassConfigCallback([](auto &TM, auto &PM, 
auto *TPC) {
+outs() << "registerTargetPassConfigCallback\n";
+TPC->insertPass(&GCLoweringID, &CodeGenTest::ID);
+});
+}
+
+#else
+
+// CHECK: CodeGenTest::runOnMachineFunction
+int main(int argc, char **argv) {
+return 0;
+}
+
+#endif
diff --git a/llvm/docs/WritingAnLLVMPass.rst b/llvm/docs/WritingAnLLVMPass.rst
index 484227bac38b5..770f5f6acd115 100644
--- a/llvm/docs/WritingAnLLVMPass.rst
+++ b/llvm/docs/WritingAnLLVMPass.rst
@@ -442,6 +442,23 @@ in certain circumstances (such as calling the 
``Pass::dump()`` from a
 debugger), so it should only be used to enhance debug output, it should not be
 depended on.
 
+Scheduling a MachineFunctionPass
+
+
+Backends create a ``TargetPassConfig`` and use ``addPass`` to schedule
+``MachineFunctionPass``\ es. External plugins can register a callback to modify
+and insert additional passes:
+
+.. code-block:: c++
+
+  TargetMachine::registerTargetPassConfigCallback(
+[](TargetMachine &TM, PassManager &PM, TargetPassConfig *TPC) {
+  TPC->insertPass(/* ... */);
+  TPC->substitutePass(/* ... */);
+}
+  );
+
+
 .. _writing-an-llvm-pass-interaction:
 
 Specifying interactions between passes
diff --git a/llvm/include/llvm/Target/TargetMachine.h 
b/llvm/include/llvm/Target/TargetMachine.h
index 906926729ed74..bcc1ce29b8282 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -20,10 +20,12 @@
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/PGOOptions.h"
 #include "llvm/Target/CGPassBuilderOption.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/TargetParser/Triple.h"
+#include 
 #include 
 #include 
 #include 
@@ -72,6 +74,10 @@ namespace yaml {
 struct MachineFunctionInfo;
 } // namespace yaml
 
+class TargetMachine;
+using PassConfigCallback =
+std::function;
+
 
//===--===//
 ///
 /// Primary in

[clang] [llvm] [CodeGen] Expose the extensibility of PassConfig to plugins (PR #139059)

2025-05-20 Thread via cfe-commits

https://github.com/Tcc100 updated 
https://github.com/llvm/llvm-project/pull/139059

>From 0b9f452fff11853207e0eab6108e47e8c7469295 Mon Sep 17 00:00:00 2001
From: T 
Date: Thu, 8 May 2025 11:56:00 +0200
Subject: [PATCH] [CodeGen] Expose the extensibility of PassConfig to plugins

---
 clang/test/CodeGen/passconfighook.cpp | 56 +++
 llvm/docs/WritingAnLLVMPass.rst   | 17 ++
 llvm/include/llvm/Target/TargetMachine.h  | 14 +
 llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp |  3 +
 llvm/lib/Target/TargetMachine.cpp |  3 +
 5 files changed, 93 insertions(+)
 create mode 100644 clang/test/CodeGen/passconfighook.cpp

diff --git a/clang/test/CodeGen/passconfighook.cpp 
b/clang/test/CodeGen/passconfighook.cpp
new file mode 100644
index 0..094df123f3de1
--- /dev/null
+++ b/clang/test/CodeGen/passconfighook.cpp
@@ -0,0 +1,56 @@
+// RUN: %clangxx -shared -fPIC -I??/install/include -L%llvmshlibdir %s -o %t.so
+// RUN: %clangxx -O3 -DMAIN -Xclang -load -Xclang %t.so %s -o %t-main | 
FileCheck %s
+
+#ifndef MAIN
+
+#include 
+#include 
+#include 
+#include 
+
+#define DEBUG_TYPE "codegen-test"
+#define CODEGEN_TEST_NAME "CodeGen Test Pass"
+
+using namespace llvm;
+
+namespace llvm {
+void initializeCodeGenTestPass(PassRegistry &);
+} // namespace llvm
+
+class CodeGenTest : public MachineFunctionPass {
+public:
+static char ID;
+
+CodeGenTest(): MachineFunctionPass(ID) {
+}
+
+bool runOnMachineFunction(MachineFunction &MF) override {
+outs() << "[CodeGen] CodeGenTest::runOnMachineFunction" << "\n";
+return true;
+}
+
+StringRef getPassName() const override {
+return CODEGEN_TEST_NAME;
+}
+};
+
+char CodeGenTest::ID = 0;
+INITIALIZE_PASS(CodeGenTest, DEBUG_TYPE, CODEGEN_TEST_NAME, false, false)
+
+__attribute__((constructor)) static void initCodeGenPlugin() {
+initializeCodeGenTestPass(*PassRegistry::getPassRegistry());
+
+TargetMachine::registerTargetPassConfigCallback([](auto &TM, auto &PM, 
auto *TPC) {
+outs() << "registerTargetPassConfigCallback\n";
+TPC->insertPass(&GCLoweringID, &CodeGenTest::ID);
+});
+}
+
+#else
+
+// CHECK: CodeGenTest::runOnMachineFunction
+int main(int argc, char **argv) {
+return 0;
+}
+
+#endif
diff --git a/llvm/docs/WritingAnLLVMPass.rst b/llvm/docs/WritingAnLLVMPass.rst
index 484227bac38b5..770f5f6acd115 100644
--- a/llvm/docs/WritingAnLLVMPass.rst
+++ b/llvm/docs/WritingAnLLVMPass.rst
@@ -442,6 +442,23 @@ in certain circumstances (such as calling the 
``Pass::dump()`` from a
 debugger), so it should only be used to enhance debug output, it should not be
 depended on.
 
+Scheduling a MachineFunctionPass
+
+
+Backends create a ``TargetPassConfig`` and use ``addPass`` to schedule
+``MachineFunctionPass``\ es. External plugins can register a callback to modify
+and insert additional passes:
+
+.. code-block:: c++
+
+  TargetMachine::registerTargetPassConfigCallback(
+[](TargetMachine &TM, PassManager &PM, TargetPassConfig *TPC) {
+  TPC->insertPass(/* ... */);
+  TPC->substitutePass(/* ... */);
+}
+  );
+
+
 .. _writing-an-llvm-pass-interaction:
 
 Specifying interactions between passes
diff --git a/llvm/include/llvm/Target/TargetMachine.h 
b/llvm/include/llvm/Target/TargetMachine.h
index 906926729ed74..bcc1ce29b8282 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -20,10 +20,12 @@
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/PGOOptions.h"
 #include "llvm/Target/CGPassBuilderOption.h"
 #include "llvm/Target/TargetOptions.h"
 #include "llvm/TargetParser/Triple.h"
+#include 
 #include 
 #include 
 #include 
@@ -72,6 +74,10 @@ namespace yaml {
 struct MachineFunctionInfo;
 } // namespace yaml
 
+class TargetMachine;
+using PassConfigCallback =
+std::function;
+
 
//===--===//
 ///
 /// Primary interface to the complete machine description for the target
@@ -119,6 +125,9 @@ class TargetMachine {
   std::optional PGOOption;
 
 public:
+  static ManagedStatic>
+  TargetPassConfigCallbacks;
+
   mutable TargetOptions Options;
 
   TargetMachine(const TargetMachine &) = delete;
@@ -518,6 +527,11 @@ class TargetMachine {
 
   // MachineRegisterInfo callback function
   virtual void registerMachineRegisterInfoCallback(MachineFunction &MF) const 
{}
+
+  // TargetPassConfig callback function
+  static void registerTargetPassConfigCallback(const PassConfigCallback &C) {
+TargetPassConfigCallbacks->push_back(C);
+  }
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp 
b/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp
index 4a3503a2da7db..336f1db776036 100644
--- a/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cp