Skip to content

Commit 56a8655

Browse files
authored
[CodeGen] Expose the extensibility of PassConfig to plugins (#139059)
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 since backends still use it as the default.
1 parent 953416a commit 56a8655

File tree

13 files changed

+342
-0
lines changed

13 files changed

+342
-0
lines changed

llvm/docs/WritingAnLLVMPass.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,28 @@ in certain circumstances (such as calling the ``Pass::dump()`` from a
442442
debugger), so it should only be used to enhance debug output, it should not be
443443
depended on.
444444

445+
Scheduling a MachineFunctionPass
446+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
447+
448+
Backends create a ``TargetPassConfig`` and use ``addPass`` to schedule
449+
``MachineFunctionPass``\ es. External plugins can register a callback to modify
450+
and insert additional passes:
451+
452+
.. code-block:: c++
453+
454+
RegisterTargetPassConfigCallback X{[](auto &TM, auto &PM, auto *TPC) {
455+
TPC->insertPass(/* ... */);
456+
TPC->substitutePass(/* ... */);
457+
}};
458+
459+
Note that passes still have to be registered:
460+
461+
.. code-block:: c++
462+
463+
__attribute__((constructor)) static void initCodeGenPlugin() {
464+
initializeExamplePass(*PassRegistry::getPassRegistry());
465+
}
466+
445467
.. _writing-an-llvm-pass-interaction:
446468

447469
Specifying interactions between passes
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// This file contains the registry for PassConfigCallbacks that enable changes
10+
/// to the TargetPassConfig during the initialization of TargetMachine.
11+
///
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_TARGET_REGISTERTARGETPASSCONFIGCALLBACK_H
15+
#define LLVM_TARGET_REGISTERTARGETPASSCONFIGCALLBACK_H
16+
17+
#include "TargetMachine.h"
18+
19+
namespace llvm {
20+
21+
using PassConfigCallback =
22+
std::function<void(TargetMachine &, PassManagerBase &, TargetPassConfig *)>;
23+
24+
class RegisterTargetPassConfigCallback {
25+
public:
26+
PassConfigCallback Callback;
27+
28+
explicit RegisterTargetPassConfigCallback(PassConfigCallback &&C);
29+
~RegisterTargetPassConfigCallback();
30+
};
31+
32+
void invokeGlobalTargetPassConfigCallbacks(TargetMachine &TM,
33+
PassManagerBase &PM,
34+
TargetPassConfig *PassConfig);
35+
} // namespace llvm
36+
37+
#endif // LLVM_TARGET_REGISTERTARGETPASSCONFIGCALLBACK_H

llvm/lib/CodeGen/CodeGenTargetMachineImpl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "llvm/MC/TargetRegistry.h"
3131
#include "llvm/Support/CommandLine.h"
3232
#include "llvm/Support/FormattedStream.h"
33+
#include "llvm/Target/RegisterTargetPassConfigCallback.h"
3334
#include "llvm/Target/TargetMachine.h"
3435
#include "llvm/Target/TargetOptions.h"
3536
using namespace llvm;
@@ -122,6 +123,7 @@ addPassesToGenerateCode(CodeGenTargetMachineImpl &TM, PassManagerBase &PM,
122123
PassConfig->setDisableVerify(DisableVerify);
123124
PM.add(PassConfig);
124125
PM.add(&MMIWP);
126+
invokeGlobalTargetPassConfigCallbacks(TM, PM, PassConfig);
125127

126128
if (PassConfig->addISelPasses())
127129
return nullptr;

llvm/lib/Target/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ list(APPEND LLVM_COMMON_DEPENDS intrinsics_gen)
33
list(APPEND LLVM_TABLEGEN_FLAGS -I ${LLVM_MAIN_SRC_DIR}/lib/Target)
44

55
add_llvm_component_library(LLVMTarget
6+
RegisterTargetPassConfigCallback.cpp
67
Target.cpp
78
TargetLoweringObjectFile.cpp
89
TargetMachine.cpp
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// This file contains the registry for PassConfigCallbacks that enable changes
10+
/// to the TargetPassConfig during the initialization of TargetMachine.
11+
///
12+
//===----------------------------------------------------------------------===//
13+
14+
#include "llvm/Target/RegisterTargetPassConfigCallback.h"
15+
16+
namespace llvm {
17+
// TargetPassConfig callbacks
18+
static SmallVector<RegisterTargetPassConfigCallback *, 1>
19+
TargetPassConfigCallbacks{};
20+
21+
void invokeGlobalTargetPassConfigCallbacks(TargetMachine &TM,
22+
PassManagerBase &PM,
23+
TargetPassConfig *PassConfig) {
24+
for (const RegisterTargetPassConfigCallback *Reg : TargetPassConfigCallbacks)
25+
Reg->Callback(TM, PM, PassConfig);
26+
}
27+
28+
RegisterTargetPassConfigCallback::RegisterTargetPassConfigCallback(
29+
PassConfigCallback &&C)
30+
: Callback(std::move(C)) {
31+
TargetPassConfigCallbacks.push_back(this);
32+
}
33+
34+
RegisterTargetPassConfigCallback::~RegisterTargetPassConfigCallback() {
35+
const auto &It = find(TargetPassConfigCallbacks, this);
36+
if (It != TargetPassConfigCallbacks.end())
37+
TargetPassConfigCallbacks.erase(It);
38+
}
39+
} // namespace llvm
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
; RUN: llc -load %llvmshlibdir/../unittests/CodeGen/CGPluginTest/CGTestPlugin%pluginext %s -o - | FileCheck %s
2+
; REQUIRES: native, system-linux, llvm-dylib
3+
4+
; CHECK: CodeGen Test Pass running on main
5+
define void @main() {
6+
ret void
7+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
set(LLVM_LINK_COMPONENTS
2+
${LLVM_TARGETS_TO_BUILD}
3+
Support
4+
Core
5+
Target
6+
CodeGen
7+
)
8+
9+
add_llvm_unittest(CGPluginTest
10+
PluginTest.cpp
11+
Plugin/CodeGenTestPass.cpp
12+
13+
EXPORT_SYMBOLS
14+
)
15+
target_link_libraries(CGPluginTest PRIVATE LLVMTestingSupport)
16+
17+
unset(LLVM_LINK_COMPONENTS)
18+
add_subdirectory(Plugin)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
if (NOT WIN32 AND NOT CYGWIN)
2+
unset(LLVM_LINK_COMPONENTS)
3+
add_llvm_library(CGTestPlugin MODULE BUILDTREE_ONLY
4+
CodeGenTestPass.cpp
5+
Plugin.cpp
6+
)
7+
8+
# Put PLUGIN next to the unit test executable.
9+
set_output_directory(CGTestPlugin
10+
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/../
11+
LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/../
12+
)
13+
set_target_properties(CGTestPlugin PROPERTIES FOLDER "Tests")
14+
15+
add_dependencies(CGTestPlugin intrinsics_gen vt_gen)
16+
add_dependencies(CGPluginTest CGTestPlugin)
17+
endif ()
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "CodeGenTestPass.h"
10+
11+
#include "llvm/CodeGen/MachineFrameInfo.h"
12+
#include "llvm/CodeGen/MachineFunctionPass.h"
13+
14+
using namespace llvm;
15+
16+
#define DEBUG_TYPE "codegen-test"
17+
#define CODEGEN_TEST_NAME "CodeGen Test Pass"
18+
19+
CodeGenTest::CodeGenTest() : MachineFunctionPass(ID) {}
20+
21+
bool CodeGenTest::runOnMachineFunction(MachineFunction &MF) {
22+
outs() << CODEGEN_TEST_NAME << " running on " << MF.getName()
23+
<< "\n"; // used for the lit test
24+
if (RunCallback)
25+
RunCallback();
26+
return true;
27+
}
28+
29+
StringRef CodeGenTest::getPassName() const { return CODEGEN_TEST_NAME; }
30+
31+
char CodeGenTest::ID = 0;
32+
std::function<void()> CodeGenTest::RunCallback;
33+
34+
INITIALIZE_PASS(CodeGenTest, DEBUG_TYPE, CODEGEN_TEST_NAME, false, false)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef CODEGEN_TEST_PASS
10+
#define CODEGEN_TEST_PASS
11+
12+
#include <llvm/CodeGen/MachineFunctionPass.h>
13+
14+
using namespace llvm;
15+
16+
namespace llvm {
17+
void initializeCodeGenTestPass(PassRegistry &);
18+
} // namespace llvm
19+
20+
class CodeGenTest : public MachineFunctionPass {
21+
public:
22+
static char ID;
23+
24+
CodeGenTest();
25+
26+
bool runOnMachineFunction(MachineFunction &MF) override;
27+
28+
StringRef getPassName() const override;
29+
30+
static std::function<void()> RunCallback;
31+
};
32+
33+
#endif // CODEGEN_TEST_PASS

0 commit comments

Comments
 (0)