Skip to content

Commit 911565d

Browse files
author
Yuanfang Chen
committed
[NewPM][CodeGen] Introduce machine pass and machine pass manager
machine pass could define four methods: - `PreservedAnalyses run(MachineFunction &, MachineFunctionAnalysisManager &)` - `Error doInitialization(Module &, MachineFunctionAnalysisManager &)` - `Error doFinalization(Module &, MachineFunctionAnalysisManager &)` - `Error run(Module &, MachineFunctionAnalysisManager &)` machine pass manger: - MachineFunctionAnalysisManager: Basically an AnalysisManager<MachineFunction> augmented with the ability to register and query IR analyses - MachineFunctionPassManager: support only two methods, `addPass` and `run` Reviewed By: arsenm, asbirlea, aeubanks Differential Revision: https://reviews.llvm.org/D67687
1 parent 954bd9c commit 911565d

File tree

7 files changed

+665
-2
lines changed

7 files changed

+665
-2
lines changed
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
//===- PassManager.h --- Pass management for CodeGen ------------*- C++ -*-===//
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 header defines the pass manager interface for codegen. The codegen
10+
// pipeline consists of only machine function passes. There is no container
11+
// relationship between IR module/function and machine function in terms of pass
12+
// manager organization. So there is no need for adaptor classes (for example
13+
// ModuleToMachineFunctionAdaptor). Since invalidation could only happen among
14+
// machine function passes, there is no proxy classes to handle cross-IR-unit
15+
// invalidation. IR analysis results are provided for machine function passes by
16+
// their respective analysis managers such as ModuleAnalysisManager and
17+
// FunctionAnalysisManager.
18+
//
19+
// TODO: Add MachineFunctionProperties support.
20+
//
21+
//===----------------------------------------------------------------------===//
22+
23+
#ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H
24+
#define LLVM_CODEGEN_MACHINEPASSMANAGER_H
25+
26+
#include "llvm/ADT/FunctionExtras.h"
27+
#include "llvm/ADT/SmallVector.h"
28+
#include "llvm/CodeGen/MachineFunction.h"
29+
#include "llvm/IR/PassManager.h"
30+
#include "llvm/Support/Error.h"
31+
#include "llvm/Support/type_traits.h"
32+
33+
namespace llvm {
34+
class Module;
35+
36+
extern template class AnalysisManager<MachineFunction>;
37+
38+
/// An AnalysisManager<MachineFunction> that also exposes IR analysis results.
39+
class MachineFunctionAnalysisManager : public AnalysisManager<MachineFunction> {
40+
public:
41+
using Base = AnalysisManager<MachineFunction>;
42+
43+
MachineFunctionAnalysisManager() : Base(false), FAM(nullptr), MAM(nullptr) {}
44+
MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM,
45+
ModuleAnalysisManager &MAM,
46+
bool DebugLogging = false)
47+
: Base(DebugLogging), FAM(&FAM), MAM(&MAM) {}
48+
MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default;
49+
MachineFunctionAnalysisManager &
50+
operator=(MachineFunctionAnalysisManager &&) = default;
51+
52+
/// Get the result of an analysis pass for a Function.
53+
///
54+
/// Runs the analysis if a cached result is not available.
55+
template <typename PassT> typename PassT::Result &getResult(Function &F) {
56+
return FAM->getResult<PassT>(F);
57+
}
58+
59+
/// Get the cached result of an analysis pass for a Function.
60+
///
61+
/// This method never runs the analysis.
62+
///
63+
/// \returns null if there is no cached result.
64+
template <typename PassT>
65+
typename PassT::Result *getCachedResult(Function &F) {
66+
return FAM->getCachedResult<PassT>(F);
67+
}
68+
69+
/// Get the result of an analysis pass for a Module.
70+
///
71+
/// Runs the analysis if a cached result is not available.
72+
template <typename PassT> typename PassT::Result &getResult(Module &M) {
73+
return MAM->getResult<PassT>(M);
74+
}
75+
76+
/// Get the cached result of an analysis pass for a Module.
77+
///
78+
/// This method never runs the analysis.
79+
///
80+
/// \returns null if there is no cached result.
81+
template <typename PassT> typename PassT::Result *getCachedResult(Module &M) {
82+
return MAM->getCachedResult<PassT>(M);
83+
}
84+
85+
/// Get the result of an analysis pass for a MachineFunction.
86+
///
87+
/// Runs the analysis if a cached result is not available.
88+
using Base::getResult;
89+
90+
/// Get the cached result of an analysis pass for a MachineFunction.
91+
///
92+
/// This method never runs the analysis.
93+
///
94+
/// \returns null if there is no cached result.
95+
using Base::getCachedResult;
96+
97+
// FIXME: Add LoopAnalysisManager or CGSCCAnalysisManager if needed.
98+
FunctionAnalysisManager *FAM;
99+
ModuleAnalysisManager *MAM;
100+
};
101+
102+
extern template class PassManager<MachineFunction>;
103+
104+
/// MachineFunctionPassManager adds/removes below features to/from the base
105+
/// PassManager template instantiation.
106+
///
107+
/// - Support passes that implement doInitialization/doFinalization. This is for
108+
/// machine function passes to work on module level constructs. One such pass
109+
/// is AsmPrinter.
110+
///
111+
/// - Support machine module pass which runs over the module (for example,
112+
/// MachineOutliner). A machine module pass needs to define the method:
113+
///
114+
/// ```Error run(Module &, MachineFunctionAnalysisManager &)```
115+
///
116+
/// FIXME: machine module passes still need to define the usual machine
117+
/// function pass interface, namely,
118+
/// `PreservedAnalyses run(MachineFunction &,
119+
/// MachineFunctionAnalysisManager &)`
120+
/// But this interface wouldn't be executed. It is just a placeholder
121+
/// to satisfy the pass manager type-erased inteface. This
122+
/// special-casing of machine module pass is due to its limited use
123+
/// cases and the unnecessary complexity it may bring to the machine
124+
/// pass manager.
125+
///
126+
/// - The base class `run` method is replaced by an alternative `run` method.
127+
/// See details below.
128+
///
129+
/// - Support codegening in the SCC order. Users include interprocedural
130+
/// register allocation (IPRA).
131+
class MachineFunctionPassManager
132+
: public PassManager<MachineFunction, MachineFunctionAnalysisManager> {
133+
using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>;
134+
135+
public:
136+
MachineFunctionPassManager(bool DebugLogging = false,
137+
bool RequireCodeGenSCCOrder = false)
138+
: Base(DebugLogging), RequireCodeGenSCCOrder(RequireCodeGenSCCOrder) {}
139+
MachineFunctionPassManager(MachineFunctionPassManager &&) = default;
140+
MachineFunctionPassManager &
141+
operator=(MachineFunctionPassManager &&) = default;
142+
143+
/// Run machine passes for a Module.
144+
///
145+
/// The intended use is to start the codegen pipeline for a Module. The base
146+
/// class's `run` method is deliberately hidden by this due to the observation
147+
/// that we don't yet have the use cases of compositing two instances of
148+
/// machine pass managers, or compositing machine pass managers with other
149+
/// types of pass managers.
150+
Error run(Module &M, MachineFunctionAnalysisManager &MFAM);
151+
152+
template <typename PassT> void addPass(PassT &&Pass) {
153+
Base::addPass(std::forward<PassT>(Pass));
154+
PassConceptT *P = Passes.back().get();
155+
addDoInitialization<PassT>(P);
156+
addDoFinalization<PassT>(P);
157+
158+
// Add machine module pass.
159+
addRunOnModule<PassT>(P);
160+
}
161+
162+
private:
163+
template <typename PassT>
164+
using has_init_t = decltype(std::declval<PassT &>().doInitialization(
165+
std::declval<Module &>(),
166+
std::declval<MachineFunctionAnalysisManager &>()));
167+
168+
template <typename PassT>
169+
std::enable_if_t<!is_detected<has_init_t, PassT>::value>
170+
addDoInitialization(PassConceptT *Pass) {}
171+
172+
template <typename PassT>
173+
std::enable_if_t<is_detected<has_init_t, PassT>::value>
174+
addDoInitialization(PassConceptT *Pass) {
175+
using PassModelT =
176+
detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
177+
MachineFunctionAnalysisManager>;
178+
auto *P = static_cast<PassModelT *>(Pass);
179+
InitializationFuncs.emplace_back(
180+
[=](Module &M, MachineFunctionAnalysisManager &MFAM) {
181+
return P->Pass.doInitialization(M, MFAM);
182+
});
183+
}
184+
185+
template <typename PassT>
186+
using has_fini_t = decltype(std::declval<PassT &>().doFinalization(
187+
std::declval<Module &>(),
188+
std::declval<MachineFunctionAnalysisManager &>()));
189+
190+
template <typename PassT>
191+
std::enable_if_t<!is_detected<has_fini_t, PassT>::value>
192+
addDoFinalization(PassConceptT *Pass) {}
193+
194+
template <typename PassT>
195+
std::enable_if_t<is_detected<has_fini_t, PassT>::value>
196+
addDoFinalization(PassConceptT *Pass) {
197+
using PassModelT =
198+
detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
199+
MachineFunctionAnalysisManager>;
200+
auto *P = static_cast<PassModelT *>(Pass);
201+
FinalizationFuncs.emplace_back(
202+
[=](Module &M, MachineFunctionAnalysisManager &MFAM) {
203+
return P->Pass.doFinalization(M, MFAM);
204+
});
205+
}
206+
207+
template <typename PassT>
208+
using is_machine_module_pass_t = decltype(std::declval<PassT &>().run(
209+
std::declval<Module &>(),
210+
std::declval<MachineFunctionAnalysisManager &>()));
211+
212+
template <typename PassT>
213+
using is_machine_function_pass_t = decltype(std::declval<PassT &>().run(
214+
std::declval<MachineFunction &>(),
215+
std::declval<MachineFunctionAnalysisManager &>()));
216+
217+
template <typename PassT>
218+
std::enable_if_t<!is_detected<is_machine_module_pass_t, PassT>::value>
219+
addRunOnModule(PassConceptT *Pass) {}
220+
221+
template <typename PassT>
222+
std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value>
223+
addRunOnModule(PassConceptT *Pass) {
224+
static_assert(is_detected<is_machine_function_pass_t, PassT>::value,
225+
"machine module pass needs to define machine function pass "
226+
"api. sorry.");
227+
228+
using PassModelT =
229+
detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
230+
MachineFunctionAnalysisManager>;
231+
auto *P = static_cast<PassModelT *>(Pass);
232+
MachineModulePasses.emplace(
233+
Passes.size() - 1,
234+
[=](Module &M, MachineFunctionAnalysisManager &MFAM) {
235+
return P->Pass.run(M, MFAM);
236+
});
237+
}
238+
239+
using FuncTy = Error(Module &, MachineFunctionAnalysisManager &);
240+
SmallVector<llvm::unique_function<FuncTy>, 4> InitializationFuncs;
241+
SmallVector<llvm::unique_function<FuncTy>, 4> FinalizationFuncs;
242+
243+
using PassIndex = decltype(Passes)::size_type;
244+
std::map<PassIndex, llvm::unique_function<FuncTy>> MachineModulePasses;
245+
246+
// Run codegen in the SCC order.
247+
bool RequireCodeGenSCCOrder;
248+
};
249+
250+
} // end namespace llvm
251+
252+
#endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H

llvm/include/llvm/IR/PassManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ class PassManager : public PassInfoMixin<
558558

559559
static bool isRequired() { return true; }
560560

561-
private:
561+
protected:
562562
using PassConceptT =
563563
detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
564564

llvm/lib/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ add_llvm_component_library(LLVMCodeGen
9292
MachineOperand.cpp
9393
MachineOptimizationRemarkEmitter.cpp
9494
MachineOutliner.cpp
95+
MachinePassManager.cpp
9596
MachinePipeliner.cpp
9697
MachinePostDominators.cpp
9798
MachineRegionInfo.cpp

llvm/lib/CodeGen/LLVMBuild.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ subdirectories = AsmPrinter SelectionDAG MIRParser GlobalISel
2121
type = Library
2222
name = CodeGen
2323
parent = Libraries
24-
required_libraries = Analysis BitReader BitWriter Core MC ProfileData Scalar Support Target TransformUtils
24+
required_libraries = Analysis BitReader BitWriter Core MC Passes ProfileData Scalar Support Target TransformUtils
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//===---------- MachinePassManager.cpp ------------------------------------===//
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 pass management machinery for machine functions.
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "llvm/CodeGen/MachinePassManager.h"
14+
#include "llvm/CodeGen/MachineModuleInfo.h"
15+
#include "llvm/IR/PassManagerImpl.h"
16+
17+
using namespace llvm;
18+
19+
namespace llvm {
20+
template class AllAnalysesOn<MachineFunction>;
21+
template class AnalysisManager<MachineFunction>;
22+
template class PassManager<MachineFunction>;
23+
24+
Error MachineFunctionPassManager::run(Module &M,
25+
MachineFunctionAnalysisManager &MFAM) {
26+
// MachineModuleAnalysis is a module analysis pass that is never invalidated
27+
// because we don't run any module pass in codegen pipeline. This is very
28+
// important because the codegen state is stored in MMI which is the analysis
29+
// result of MachineModuleAnalysis. MMI should not be recomputed.
30+
auto &MMI = MFAM.getResult<MachineModuleAnalysis>(M);
31+
32+
assert(!RequireCodeGenSCCOrder && "not implemented");
33+
34+
if (DebugLogging) {
35+
dbgs() << "Starting " << getTypeName<MachineFunction>()
36+
<< " pass manager run.\n";
37+
}
38+
39+
for (auto &F : InitializationFuncs) {
40+
if (auto Err = F(M, MFAM))
41+
return Err;
42+
}
43+
44+
unsigned Idx = 0;
45+
size_t Size = Passes.size();
46+
do {
47+
// Run machine module passes
48+
for (; MachineModulePasses.count(Idx) && Idx != Size; ++Idx) {
49+
if (DebugLogging)
50+
dbgs() << "Running pass: " << Passes[Idx]->name() << " on "
51+
<< M.getName() << '\n';
52+
if (auto Err = MachineModulePasses.at(Idx)(M, MFAM))
53+
return Err;
54+
}
55+
56+
// Finish running all passes.
57+
if (Idx == Size)
58+
break;
59+
60+
// Run machine function passes
61+
62+
// Get index range of machine function passes.
63+
unsigned Begin = Idx;
64+
for (; !MachineModulePasses.count(Idx) && Idx != Size; ++Idx)
65+
;
66+
67+
for (Function &F : M) {
68+
// Do not codegen any 'available_externally' functions at all, they have
69+
// definitions outside the translation unit.
70+
if (F.hasAvailableExternallyLinkage())
71+
continue;
72+
73+
MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
74+
PassInstrumentation PI = MFAM.getResult<PassInstrumentationAnalysis>(MF);
75+
76+
for (unsigned I = Begin, E = Idx; I != E; ++I) {
77+
auto *P = Passes[I].get();
78+
79+
if (!PI.runBeforePass<MachineFunction>(*P, MF))
80+
continue;
81+
82+
// TODO: EmitSizeRemarks
83+
PreservedAnalyses PassPA = P->run(MF, MFAM);
84+
PI.runAfterPass(*P, MF);
85+
MFAM.invalidate(MF, PassPA);
86+
}
87+
}
88+
} while (true);
89+
90+
for (auto &F : FinalizationFuncs) {
91+
if (auto Err = F(M, MFAM))
92+
return Err;
93+
}
94+
95+
if (DebugLogging) {
96+
dbgs() << "Finished " << getTypeName<MachineFunction>()
97+
<< " pass manager run.\n";
98+
}
99+
100+
return Error::success();
101+
}
102+
103+
} // namespace llvm

llvm/unittests/CodeGen/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS
77
Core
88
MC
99
MIRParser
10+
Passes
1011
SelectionDAG
1112
Support
1213
Target
@@ -20,6 +21,7 @@ add_llvm_unittest(CodeGenTests
2021
MachineInstrBundleIteratorTest.cpp
2122
MachineInstrTest.cpp
2223
MachineOperandTest.cpp
24+
PassManagerTest.cpp
2325
ScalableVectorMVTsTest.cpp
2426
TypeTraitsTest.cpp
2527
TargetOptionsTest.cpp

0 commit comments

Comments
 (0)