llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: None (Tcc100) <details> <summary>Changes</summary> 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 0000000000000..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 <llvm/Target/TargetMachine.h> +#include <llvm/CodeGen/TargetPassConfig.h> +#include <llvm/CodeGen/MachineFunctionPass.h> +#include <llvm/CodeGen/Passes.h> + +#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 <functional> #include <optional> #include <string> #include <utility> @@ -72,6 +74,10 @@ namespace yaml { struct MachineFunctionInfo; } // namespace yaml +class TargetMachine; +using PassConfigCallback = + std::function<void(TargetMachine &, PassManagerBase &, TargetPassConfig *)>; + //===----------------------------------------------------------------------===// /// /// Primary interface to the complete machine description for the target @@ -119,6 +125,9 @@ class TargetMachine { std::optional<PGOOptions> PGOOption; public: + static ManagedStatic<SmallVector<PassConfigCallback, 1>> + 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.cpp +++ b/llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp @@ -119,6 +119,9 @@ addPassesToGenerateCode(CodeGenTargetMachineImpl &TM, PassManagerBase &PM, PM.add(PassConfig); PM.add(&MMIWP); + for (auto& C : *TargetMachine::TargetPassConfigCallbacks) + C(TM, PM, PassConfig); + if (PassConfig->addISelPasses()) return nullptr; PassConfig->addMachinePasses(); diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp index 69b6e26e602f6..c43e2ba00f733 100644 --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -332,3 +332,6 @@ std::pair<int, int> TargetMachine::parseBinutilsVersion(StringRef Version) { Version.consumeInteger(10, Ret.second); return Ret; } + +// TargetPassConfig callbacks +ManagedStatic<SmallVector<PassConfigCallback, 1>> TargetMachine::TargetPassConfigCallbacks{}; `````````` </details> 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