In new pass system, `MachineFunction` could be an analysis result again, machine module pass can now fetch them from analysis manager. `MachineModuleInfo` no longer owns them. Remove `FreeMachineFunctionPass`, replaced by `InvalidateAnalysisPass<MachineFunctionAnalysis>`. Now `FreeMachineFunction` is replaced by `InvalidateAnalysisPass<MachineFunctionAnalysis>`, the workaround in `MachineFunctionPassManager` is no longer needed, there is no difference between `unittests/MIR/PassBuilderCallbacksTest.cpp` and `unittests/IR/PassBuilderCallbacksTest.cpp`.
253 lines
9.3 KiB
C++
253 lines
9.3 KiB
C++
//===- PassManager.h --- Pass management for CodeGen ------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This header defines the pass manager interface for codegen. The codegen
|
|
// pipeline consists of only machine function passes. There is no container
|
|
// relationship between IR module/function and machine function in terms of pass
|
|
// manager organization. So there is no need for adaptor classes (for example
|
|
// ModuleToMachineFunctionAdaptor). Since invalidation could only happen among
|
|
// machine function passes, there is no proxy classes to handle cross-IR-unit
|
|
// invalidation. IR analysis results are provided for machine function passes by
|
|
// their respective analysis managers such as ModuleAnalysisManager and
|
|
// FunctionAnalysisManager.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CODEGEN_MACHINEPASSMANAGER_H
|
|
#define LLVM_CODEGEN_MACHINEPASSMANAGER_H
|
|
|
|
#include "llvm/ADT/FunctionExtras.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/IR/PassManager.h"
|
|
#include "llvm/IR/PassManagerInternal.h"
|
|
#include "llvm/Support/Error.h"
|
|
|
|
namespace llvm {
|
|
class Module;
|
|
class Function;
|
|
class MachineFunction;
|
|
|
|
extern template class AnalysisManager<MachineFunction>;
|
|
using MachineFunctionAnalysisManager = AnalysisManager<MachineFunction>;
|
|
|
|
namespace detail {
|
|
|
|
template <typename PassT>
|
|
struct MachinePassModel
|
|
: PassModel<MachineFunction, PassT, MachineFunctionAnalysisManager> {
|
|
explicit MachinePassModel(PassT &&Pass)
|
|
: PassModel<MachineFunction, PassT, MachineFunctionAnalysisManager>(
|
|
std::move(Pass)) {}
|
|
|
|
friend void swap(MachinePassModel &LHS, MachinePassModel &RHS) {
|
|
using std::swap;
|
|
swap(LHS.Pass, RHS.Pass);
|
|
}
|
|
|
|
MachinePassModel &operator=(MachinePassModel RHS) {
|
|
swap(*this, RHS);
|
|
return *this;
|
|
}
|
|
|
|
MachinePassModel &operator=(const MachinePassModel &) = delete;
|
|
PreservedAnalyses run(MachineFunction &IR,
|
|
MachineFunctionAnalysisManager &AM) override {
|
|
#ifndef NDEBUG
|
|
if constexpr (is_detected<has_get_required_properties_t, PassT>::value) {
|
|
auto &MFProps = IR.getProperties();
|
|
auto RequiredProperties = PassT::getRequiredProperties();
|
|
if (!MFProps.verifyRequiredProperties(RequiredProperties)) {
|
|
errs() << "MachineFunctionProperties required by " << PassT::name()
|
|
<< " pass are not met by function " << IR.getName() << ".\n"
|
|
<< "Required properties: ";
|
|
RequiredProperties.print(errs());
|
|
errs() << "\nCurrent properties: ";
|
|
MFProps.print(errs());
|
|
errs() << '\n';
|
|
report_fatal_error("MachineFunctionProperties check failed");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
auto PA = this->Pass.run(IR, AM);
|
|
|
|
if constexpr (is_detected<has_get_set_properties_t, PassT>::value)
|
|
IR.getProperties().set(PassT::getSetProperties());
|
|
if constexpr (is_detected<has_get_cleared_properties_t, PassT>::value)
|
|
IR.getProperties().reset(PassT::getClearedProperties());
|
|
return PA;
|
|
}
|
|
|
|
private:
|
|
template <typename T>
|
|
using has_get_required_properties_t =
|
|
decltype(std::declval<T &>().getRequiredProperties());
|
|
|
|
template <typename T>
|
|
using has_get_set_properties_t =
|
|
decltype(std::declval<T &>().getSetProperties());
|
|
|
|
template <typename T>
|
|
using has_get_cleared_properties_t =
|
|
decltype(std::declval<T &>().getClearedProperties());
|
|
};
|
|
} // namespace detail
|
|
|
|
using MachineFunctionAnalysisManagerModuleProxy =
|
|
InnerAnalysisManagerProxy<MachineFunctionAnalysisManager, Module>;
|
|
|
|
template <>
|
|
bool MachineFunctionAnalysisManagerModuleProxy::Result::invalidate(
|
|
Module &M, const PreservedAnalyses &PA,
|
|
ModuleAnalysisManager::Invalidator &Inv);
|
|
extern template class InnerAnalysisManagerProxy<MachineFunctionAnalysisManager,
|
|
Module>;
|
|
using MachineFunctionAnalysisManagerFunctionProxy =
|
|
InnerAnalysisManagerProxy<MachineFunctionAnalysisManager, Function>;
|
|
|
|
template <>
|
|
bool MachineFunctionAnalysisManagerFunctionProxy::Result::invalidate(
|
|
Function &F, const PreservedAnalyses &PA,
|
|
FunctionAnalysisManager::Invalidator &Inv);
|
|
extern template class InnerAnalysisManagerProxy<MachineFunctionAnalysisManager,
|
|
Function>;
|
|
|
|
extern template class OuterAnalysisManagerProxy<ModuleAnalysisManager,
|
|
MachineFunction>;
|
|
/// Provide the \c ModuleAnalysisManager to \c Function proxy.
|
|
using ModuleAnalysisManagerMachineFunctionProxy =
|
|
OuterAnalysisManagerProxy<ModuleAnalysisManager, MachineFunction>;
|
|
|
|
class FunctionAnalysisManagerMachineFunctionProxy
|
|
: public AnalysisInfoMixin<FunctionAnalysisManagerMachineFunctionProxy> {
|
|
public:
|
|
class Result {
|
|
public:
|
|
explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
|
|
|
|
Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {
|
|
// We have to null out the analysis manager in the moved-from state
|
|
// because we are taking ownership of the responsibilty to clear the
|
|
// analysis state.
|
|
Arg.FAM = nullptr;
|
|
}
|
|
|
|
Result &operator=(Result &&RHS) {
|
|
FAM = RHS.FAM;
|
|
// We have to null out the analysis manager in the moved-from state
|
|
// because we are taking ownership of the responsibilty to clear the
|
|
// analysis state.
|
|
RHS.FAM = nullptr;
|
|
return *this;
|
|
}
|
|
|
|
/// Accessor for the analysis manager.
|
|
FunctionAnalysisManager &getManager() { return *FAM; }
|
|
|
|
/// Handler for invalidation of the outer IR unit, \c IRUnitT.
|
|
///
|
|
/// If the proxy analysis itself is not preserved, we assume that the set of
|
|
/// inner IR objects contained in IRUnit may have changed. In this case,
|
|
/// we have to call \c clear() on the inner analysis manager, as it may now
|
|
/// have stale pointers to its inner IR objects.
|
|
///
|
|
/// Regardless of whether the proxy analysis is marked as preserved, all of
|
|
/// the analyses in the inner analysis manager are potentially invalidated
|
|
/// based on the set of preserved analyses.
|
|
bool invalidate(MachineFunction &IR, const PreservedAnalyses &PA,
|
|
MachineFunctionAnalysisManager::Invalidator &Inv);
|
|
|
|
private:
|
|
FunctionAnalysisManager *FAM;
|
|
};
|
|
|
|
explicit FunctionAnalysisManagerMachineFunctionProxy(
|
|
FunctionAnalysisManager &FAM)
|
|
: FAM(&FAM) {}
|
|
|
|
/// Run the analysis pass and create our proxy result object.
|
|
///
|
|
/// This doesn't do any interesting work; it is primarily used to insert our
|
|
/// proxy result object into the outer analysis cache so that we can proxy
|
|
/// invalidation to the inner analysis manager.
|
|
Result run(MachineFunction &, MachineFunctionAnalysisManager &) {
|
|
return Result(*FAM);
|
|
}
|
|
|
|
static AnalysisKey Key;
|
|
|
|
private:
|
|
FunctionAnalysisManager *FAM;
|
|
};
|
|
|
|
class FunctionToMachineFunctionPassAdaptor
|
|
: public PassInfoMixin<FunctionToMachineFunctionPassAdaptor> {
|
|
public:
|
|
using PassConceptT =
|
|
detail::PassConcept<MachineFunction, MachineFunctionAnalysisManager>;
|
|
|
|
explicit FunctionToMachineFunctionPassAdaptor(
|
|
std::unique_ptr<PassConceptT> Pass)
|
|
: Pass(std::move(Pass)) {}
|
|
|
|
/// Runs the function pass across every function in the function.
|
|
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
|
|
void printPipeline(raw_ostream &OS,
|
|
function_ref<StringRef(StringRef)> MapClassName2PassName);
|
|
|
|
static bool isRequired() { return true; }
|
|
|
|
private:
|
|
std::unique_ptr<PassConceptT> Pass;
|
|
};
|
|
|
|
template <typename MachineFunctionPassT>
|
|
FunctionToMachineFunctionPassAdaptor
|
|
createFunctionToMachineFunctionPassAdaptor(MachineFunctionPassT &&Pass) {
|
|
using PassModelT = detail::PassModel<MachineFunction, MachineFunctionPassT,
|
|
MachineFunctionAnalysisManager>;
|
|
// Do not use make_unique, it causes too many template instantiations,
|
|
// causing terrible compile times.
|
|
return FunctionToMachineFunctionPassAdaptor(
|
|
std::unique_ptr<FunctionToMachineFunctionPassAdaptor::PassConceptT>(
|
|
new PassModelT(std::forward<MachineFunctionPassT>(Pass))));
|
|
}
|
|
|
|
template <>
|
|
template <typename PassT>
|
|
void PassManager<MachineFunction>::addPass(PassT &&Pass) {
|
|
using MachinePassModelT = detail::MachinePassModel<PassT>;
|
|
// Do not use make_unique or emplace_back, they cause too many template
|
|
// instantiations, causing terrible compile times.
|
|
if constexpr (std::is_same_v<PassT, PassManager<MachineFunction>>) {
|
|
for (auto &P : Pass.Passes)
|
|
Passes.push_back(std::move(P));
|
|
} else {
|
|
Passes.push_back(std::unique_ptr<MachinePassModelT>(
|
|
new MachinePassModelT(std::forward<PassT>(Pass))));
|
|
}
|
|
}
|
|
|
|
template <>
|
|
PreservedAnalyses
|
|
PassManager<MachineFunction>::run(MachineFunction &,
|
|
AnalysisManager<MachineFunction> &);
|
|
extern template class PassManager<MachineFunction>;
|
|
|
|
/// Convenience typedef for a pass manager over functions.
|
|
using MachineFunctionPassManager = PassManager<MachineFunction>;
|
|
|
|
/// Returns the minimum set of Analyses that all machine function passes must
|
|
/// preserve.
|
|
PreservedAnalyses getMachineFunctionPassPreservedAnalyses();
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H
|