1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

Reland "Revert "[NewPM][CodeGen] Introduce machine pass and machine pass manager""

This relands commit 320eab2d558fde0b61437e9b9075bfd301c2c474.

The test failed because it was looking for x86-linux target
unconditionally. Now it gets the default target.
This commit is contained in:
Yuanfang Chen 2020-08-07 12:57:38 -07:00
parent dee6e5cc20
commit 526e29b5b9
7 changed files with 671 additions and 2 deletions

View File

@ -0,0 +1,252 @@
//===- 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.
//
// TODO: Add MachineFunctionProperties support.
//
//===----------------------------------------------------------------------===//
#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/Support/Error.h"
#include "llvm/Support/type_traits.h"
namespace llvm {
class Module;
extern template class AnalysisManager<MachineFunction>;
/// An AnalysisManager<MachineFunction> that also exposes IR analysis results.
class MachineFunctionAnalysisManager : public AnalysisManager<MachineFunction> {
public:
using Base = AnalysisManager<MachineFunction>;
MachineFunctionAnalysisManager() : Base(false), FAM(nullptr), MAM(nullptr) {}
MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM,
ModuleAnalysisManager &MAM,
bool DebugLogging = false)
: Base(DebugLogging), FAM(&FAM), MAM(&MAM) {}
MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default;
MachineFunctionAnalysisManager &
operator=(MachineFunctionAnalysisManager &&) = default;
/// Get the result of an analysis pass for a Function.
///
/// Runs the analysis if a cached result is not available.
template <typename PassT> typename PassT::Result &getResult(Function &F) {
return FAM->getResult<PassT>(F);
}
/// Get the cached result of an analysis pass for a Function.
///
/// This method never runs the analysis.
///
/// \returns null if there is no cached result.
template <typename PassT>
typename PassT::Result *getCachedResult(Function &F) {
return FAM->getCachedResult<PassT>(F);
}
/// Get the result of an analysis pass for a Module.
///
/// Runs the analysis if a cached result is not available.
template <typename PassT> typename PassT::Result &getResult(Module &M) {
return MAM->getResult<PassT>(M);
}
/// Get the cached result of an analysis pass for a Module.
///
/// This method never runs the analysis.
///
/// \returns null if there is no cached result.
template <typename PassT> typename PassT::Result *getCachedResult(Module &M) {
return MAM->getCachedResult<PassT>(M);
}
/// Get the result of an analysis pass for a MachineFunction.
///
/// Runs the analysis if a cached result is not available.
using Base::getResult;
/// Get the cached result of an analysis pass for a MachineFunction.
///
/// This method never runs the analysis.
///
/// \returns null if there is no cached result.
using Base::getCachedResult;
// FIXME: Add LoopAnalysisManager or CGSCCAnalysisManager if needed.
FunctionAnalysisManager *FAM;
ModuleAnalysisManager *MAM;
};
extern template class PassManager<MachineFunction>;
/// MachineFunctionPassManager adds/removes below features to/from the base
/// PassManager template instantiation.
///
/// - Support passes that implement doInitialization/doFinalization. This is for
/// machine function passes to work on module level constructs. One such pass
/// is AsmPrinter.
///
/// - Support machine module pass which runs over the module (for example,
/// MachineOutliner). A machine module pass needs to define the method:
///
/// ```Error run(Module &, MachineFunctionAnalysisManager &)```
///
/// FIXME: machine module passes still need to define the usual machine
/// function pass interface, namely,
/// `PreservedAnalyses run(MachineFunction &,
/// MachineFunctionAnalysisManager &)`
/// But this interface wouldn't be executed. It is just a placeholder
/// to satisfy the pass manager type-erased inteface. This
/// special-casing of machine module pass is due to its limited use
/// cases and the unnecessary complexity it may bring to the machine
/// pass manager.
///
/// - The base class `run` method is replaced by an alternative `run` method.
/// See details below.
///
/// - Support codegening in the SCC order. Users include interprocedural
/// register allocation (IPRA).
class MachineFunctionPassManager
: public PassManager<MachineFunction, MachineFunctionAnalysisManager> {
using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>;
public:
MachineFunctionPassManager(bool DebugLogging = false,
bool RequireCodeGenSCCOrder = false)
: Base(DebugLogging), RequireCodeGenSCCOrder(RequireCodeGenSCCOrder) {}
MachineFunctionPassManager(MachineFunctionPassManager &&) = default;
MachineFunctionPassManager &
operator=(MachineFunctionPassManager &&) = default;
/// Run machine passes for a Module.
///
/// The intended use is to start the codegen pipeline for a Module. The base
/// class's `run` method is deliberately hidden by this due to the observation
/// that we don't yet have the use cases of compositing two instances of
/// machine pass managers, or compositing machine pass managers with other
/// types of pass managers.
Error run(Module &M, MachineFunctionAnalysisManager &MFAM);
template <typename PassT> void addPass(PassT &&Pass) {
Base::addPass(std::forward<PassT>(Pass));
PassConceptT *P = Passes.back().get();
addDoInitialization<PassT>(P);
addDoFinalization<PassT>(P);
// Add machine module pass.
addRunOnModule<PassT>(P);
}
private:
template <typename PassT>
using has_init_t = decltype(std::declval<PassT &>().doInitialization(
std::declval<Module &>(),
std::declval<MachineFunctionAnalysisManager &>()));
template <typename PassT>
std::enable_if_t<!is_detected<has_init_t, PassT>::value>
addDoInitialization(PassConceptT *Pass) {}
template <typename PassT>
std::enable_if_t<is_detected<has_init_t, PassT>::value>
addDoInitialization(PassConceptT *Pass) {
using PassModelT =
detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
MachineFunctionAnalysisManager>;
auto *P = static_cast<PassModelT *>(Pass);
InitializationFuncs.emplace_back(
[=](Module &M, MachineFunctionAnalysisManager &MFAM) {
return P->Pass.doInitialization(M, MFAM);
});
}
template <typename PassT>
using has_fini_t = decltype(std::declval<PassT &>().doFinalization(
std::declval<Module &>(),
std::declval<MachineFunctionAnalysisManager &>()));
template <typename PassT>
std::enable_if_t<!is_detected<has_fini_t, PassT>::value>
addDoFinalization(PassConceptT *Pass) {}
template <typename PassT>
std::enable_if_t<is_detected<has_fini_t, PassT>::value>
addDoFinalization(PassConceptT *Pass) {
using PassModelT =
detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
MachineFunctionAnalysisManager>;
auto *P = static_cast<PassModelT *>(Pass);
FinalizationFuncs.emplace_back(
[=](Module &M, MachineFunctionAnalysisManager &MFAM) {
return P->Pass.doFinalization(M, MFAM);
});
}
template <typename PassT>
using is_machine_module_pass_t = decltype(std::declval<PassT &>().run(
std::declval<Module &>(),
std::declval<MachineFunctionAnalysisManager &>()));
template <typename PassT>
using is_machine_function_pass_t = decltype(std::declval<PassT &>().run(
std::declval<MachineFunction &>(),
std::declval<MachineFunctionAnalysisManager &>()));
template <typename PassT>
std::enable_if_t<!is_detected<is_machine_module_pass_t, PassT>::value>
addRunOnModule(PassConceptT *Pass) {}
template <typename PassT>
std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value>
addRunOnModule(PassConceptT *Pass) {
static_assert(is_detected<is_machine_function_pass_t, PassT>::value,
"machine module pass needs to define machine function pass "
"api. sorry.");
using PassModelT =
detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
MachineFunctionAnalysisManager>;
auto *P = static_cast<PassModelT *>(Pass);
MachineModulePasses.emplace(
Passes.size() - 1,
[=](Module &M, MachineFunctionAnalysisManager &MFAM) {
return P->Pass.run(M, MFAM);
});
}
using FuncTy = Error(Module &, MachineFunctionAnalysisManager &);
SmallVector<llvm::unique_function<FuncTy>, 4> InitializationFuncs;
SmallVector<llvm::unique_function<FuncTy>, 4> FinalizationFuncs;
using PassIndex = decltype(Passes)::size_type;
std::map<PassIndex, llvm::unique_function<FuncTy>> MachineModulePasses;
// Run codegen in the SCC order.
bool RequireCodeGenSCCOrder;
};
} // end namespace llvm
#endif // LLVM_CODEGEN_MACHINEPASSMANAGER_H

View File

@ -558,7 +558,7 @@ public:
static bool isRequired() { return true; }
private:
protected:
using PassConceptT =
detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;

View File

@ -92,6 +92,7 @@ add_llvm_component_library(LLVMCodeGen
MachineOperand.cpp
MachineOptimizationRemarkEmitter.cpp
MachineOutliner.cpp
MachinePassManager.cpp
MachinePipeliner.cpp
MachinePostDominators.cpp
MachineRegionInfo.cpp

View File

@ -21,4 +21,4 @@ subdirectories = AsmPrinter SelectionDAG MIRParser GlobalISel
type = Library
name = CodeGen
parent = Libraries
required_libraries = Analysis BitReader BitWriter Core MC ProfileData Scalar Support Target TransformUtils
required_libraries = Analysis BitReader BitWriter Core MC Passes ProfileData Scalar Support Target TransformUtils

View File

@ -0,0 +1,104 @@
//===---------- MachinePassManager.cpp ------------------------------------===//
//
// 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 file contains the pass management machinery for machine functions.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/PassManagerImpl.h"
using namespace llvm;
namespace llvm {
template class AllAnalysesOn<MachineFunction>;
template class AnalysisManager<MachineFunction>;
template class PassManager<MachineFunction>;
Error MachineFunctionPassManager::run(Module &M,
MachineFunctionAnalysisManager &MFAM) {
// MachineModuleAnalysis is a module analysis pass that is never invalidated
// because we don't run any module pass in codegen pipeline. This is very
// important because the codegen state is stored in MMI which is the analysis
// result of MachineModuleAnalysis. MMI should not be recomputed.
auto &MMI = MFAM.getResult<MachineModuleAnalysis>(M);
(void)RequireCodeGenSCCOrder;
assert(!RequireCodeGenSCCOrder && "not implemented");
if (DebugLogging) {
dbgs() << "Starting " << getTypeName<MachineFunction>()
<< " pass manager run.\n";
}
for (auto &F : InitializationFuncs) {
if (auto Err = F(M, MFAM))
return Err;
}
unsigned Idx = 0;
size_t Size = Passes.size();
do {
// Run machine module passes
for (; MachineModulePasses.count(Idx) && Idx != Size; ++Idx) {
if (DebugLogging)
dbgs() << "Running pass: " << Passes[Idx]->name() << " on "
<< M.getName() << '\n';
if (auto Err = MachineModulePasses.at(Idx)(M, MFAM))
return Err;
}
// Finish running all passes.
if (Idx == Size)
break;
// Run machine function passes
// Get index range of machine function passes.
unsigned Begin = Idx;
for (; !MachineModulePasses.count(Idx) && Idx != Size; ++Idx)
;
for (Function &F : M) {
// Do not codegen any 'available_externally' functions at all, they have
// definitions outside the translation unit.
if (F.hasAvailableExternallyLinkage())
continue;
MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
PassInstrumentation PI = MFAM.getResult<PassInstrumentationAnalysis>(MF);
for (unsigned I = Begin, E = Idx; I != E; ++I) {
auto *P = Passes[I].get();
if (!PI.runBeforePass<MachineFunction>(*P, MF))
continue;
// TODO: EmitSizeRemarks
PreservedAnalyses PassPA = P->run(MF, MFAM);
PI.runAfterPass(*P, MF);
MFAM.invalidate(MF, PassPA);
}
}
} while (true);
for (auto &F : FinalizationFuncs) {
if (auto Err = F(M, MFAM))
return Err;
}
if (DebugLogging) {
dbgs() << "Finished " << getTypeName<MachineFunction>()
<< " pass manager run.\n";
}
return Error::success();
}
} // namespace llvm

View File

@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS
Core
MC
MIRParser
Passes
SelectionDAG
Support
Target
@ -20,6 +21,7 @@ add_llvm_unittest(CodeGenTests
MachineInstrBundleIteratorTest.cpp
MachineInstrTest.cpp
MachineOperandTest.cpp
PassManagerTest.cpp
ScalableVectorMVTsTest.cpp
TypeTraitsTest.cpp
TargetOptionsTest.cpp

View File

@ -0,0 +1,310 @@
//===- llvm/unittest/CodeGen/PassManager.cpp - PassManager tests ----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/CGSCCPassManager.h"
#include "llvm/Analysis/LoopAnalysisManager.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachinePassManager.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Passes/PassBuilder.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
public:
struct Result {
Result(int Count) : InstructionCount(Count) {}
int InstructionCount;
};
/// Run the analysis pass over the function and return a result.
Result run(Function &F, FunctionAnalysisManager &AM) {
int Count = 0;
for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI)
for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
++II)
++Count;
return Result(Count);
}
private:
friend AnalysisInfoMixin<TestFunctionAnalysis>;
static AnalysisKey Key;
};
AnalysisKey TestFunctionAnalysis::Key;
class TestMachineFunctionAnalysis
: public AnalysisInfoMixin<TestMachineFunctionAnalysis> {
public:
struct Result {
Result(int Count) : InstructionCount(Count) {}
int InstructionCount;
};
/// Run the analysis pass over the machine function and return a result.
Result run(MachineFunction &MF, MachineFunctionAnalysisManager::Base &AM) {
auto &MFAM = static_cast<MachineFunctionAnalysisManager &>(AM);
// Query function analysis result.
TestFunctionAnalysis::Result &FAR =
MFAM.getResult<TestFunctionAnalysis>(MF.getFunction());
// + 5
return FAR.InstructionCount;
}
private:
friend AnalysisInfoMixin<TestMachineFunctionAnalysis>;
static AnalysisKey Key;
};
AnalysisKey TestMachineFunctionAnalysis::Key;
const std::string DoInitErrMsg = "doInitialization failed";
const std::string DoFinalErrMsg = "doFinalization failed";
struct TestMachineFunctionPass : public PassInfoMixin<TestMachineFunctionPass> {
TestMachineFunctionPass(int &Count, std::vector<int> &BeforeInitialization,
std::vector<int> &BeforeFinalization,
std::vector<int> &MachineFunctionPassCount)
: Count(Count), BeforeInitialization(BeforeInitialization),
BeforeFinalization(BeforeFinalization),
MachineFunctionPassCount(MachineFunctionPassCount) {}
Error doInitialization(Module &M, MachineFunctionAnalysisManager &MFAM) {
// Force doInitialization fail by starting with big `Count`.
if (Count > 10000)
return make_error<StringError>(DoInitErrMsg, inconvertibleErrorCode());
// + 1
++Count;
BeforeInitialization.push_back(Count);
return Error::success();
}
Error doFinalization(Module &M, MachineFunctionAnalysisManager &MFAM) {
// Force doFinalization fail by starting with big `Count`.
if (Count > 1000)
return make_error<StringError>(DoFinalErrMsg, inconvertibleErrorCode());
// + 1
++Count;
BeforeFinalization.push_back(Count);
return Error::success();
}
PreservedAnalyses run(MachineFunction &MF,
MachineFunctionAnalysisManager &MFAM) {
// Query function analysis result.
TestFunctionAnalysis::Result &FAR =
MFAM.getResult<TestFunctionAnalysis>(MF.getFunction());
// 3 + 1 + 1 = 5
Count += FAR.InstructionCount;
// Query module analysis result.
MachineModuleInfo &MMI =
MFAM.getResult<MachineModuleAnalysis>(*MF.getFunction().getParent());
// 1 + 1 + 1 = 3
Count += (MMI.getModule() == MF.getFunction().getParent());
// Query machine function analysis result.
TestMachineFunctionAnalysis::Result &MFAR =
MFAM.getResult<TestMachineFunctionAnalysis>(MF);
// 3 + 1 + 1 = 5
Count += MFAR.InstructionCount;
MachineFunctionPassCount.push_back(Count);
return PreservedAnalyses::none();
}
int &Count;
std::vector<int> &BeforeInitialization;
std::vector<int> &BeforeFinalization;
std::vector<int> &MachineFunctionPassCount;
};
struct TestMachineModulePass : public PassInfoMixin<TestMachineModulePass> {
TestMachineModulePass(int &Count, std::vector<int> &MachineModulePassCount)
: Count(Count), MachineModulePassCount(MachineModulePassCount) {}
Error run(Module &M, MachineFunctionAnalysisManager &MFAM) {
MachineModuleInfo &MMI = MFAM.getResult<MachineModuleAnalysis>(M);
// + 1
Count += (MMI.getModule() == &M);
MachineModulePassCount.push_back(Count);
return Error::success();
}
PreservedAnalyses run(MachineFunction &MF,
MachineFunctionAnalysisManager &AM) {
llvm_unreachable(
"This should never be reached because this is machine module pass");
}
int &Count;
std::vector<int> &MachineModulePassCount;
};
std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
SMDiagnostic Err;
return parseAssemblyString(IR, Err, Context);
}
class PassManagerTest : public ::testing::Test {
protected:
LLVMContext Context;
std::unique_ptr<Module> M;
std::unique_ptr<TargetMachine> TM;
public:
PassManagerTest()
: M(parseIR(Context, "define void @f() {\n"
"entry:\n"
" call void @g()\n"
" call void @h()\n"
" ret void\n"
"}\n"
"define void @g() {\n"
" ret void\n"
"}\n"
"define void @h() {\n"
" ret void\n"
"}\n")) {
// MachineModuleAnalysis needs a TargetMachine instance.
llvm::InitializeAllTargets();
std::string TripleName = Triple::normalize(sys::getDefaultTargetTriple());
std::string Error;
const Target *TheTarget =
TargetRegistry::lookupTarget(TripleName, Error);
if (!TheTarget)
return;
TargetOptions Options;
TM.reset(TheTarget->createTargetMachine(TripleName, "", "",
Options, None));
}
};
TEST_F(PassManagerTest, Basic) {
if (!TM)
return;
LLVMTargetMachine *LLVMTM = static_cast<LLVMTargetMachine *>(TM.get());
M->setDataLayout(TM->createDataLayout());
LoopAnalysisManager LAM(/*DebugLogging=*/true);
FunctionAnalysisManager FAM(/*DebugLogging=*/true);
CGSCCAnalysisManager CGAM(/*DebugLogging=*/true);
ModuleAnalysisManager MAM(/*DebugLogging=*/true);
PassBuilder PB(TM.get());
PB.registerModuleAnalyses(MAM);
PB.registerFunctionAnalyses(FAM);
PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
FAM.registerPass([&] { return TestFunctionAnalysis(); });
FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
MAM.registerPass([&] { return MachineModuleAnalysis(LLVMTM); });
MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
MachineFunctionAnalysisManager MFAM;
{
// Test move assignment.
MachineFunctionAnalysisManager NestedMFAM(FAM, MAM,
/*DebugLogging*/ true);
NestedMFAM.registerPass([&] { return PassInstrumentationAnalysis(); });
NestedMFAM.registerPass([&] { return TestMachineFunctionAnalysis(); });
MFAM = std::move(NestedMFAM);
}
int Count = 0;
std::vector<int> BeforeInitialization[2];
std::vector<int> BeforeFinalization[2];
std::vector<int> TestMachineFunctionCount[2];
std::vector<int> TestMachineModuleCount[2];
MachineFunctionPassManager MFPM;
{
// Test move assignment.
MachineFunctionPassManager NestedMFPM(/*DebugLogging*/ true);
NestedMFPM.addPass(TestMachineModulePass(Count, TestMachineModuleCount[0]));
NestedMFPM.addPass(TestMachineFunctionPass(Count, BeforeInitialization[0],
BeforeFinalization[0],
TestMachineFunctionCount[0]));
NestedMFPM.addPass(TestMachineModulePass(Count, TestMachineModuleCount[1]));
NestedMFPM.addPass(TestMachineFunctionPass(Count, BeforeInitialization[1],
BeforeFinalization[1],
TestMachineFunctionCount[1]));
MFPM = std::move(NestedMFPM);
}
ASSERT_FALSE(errorToBool(MFPM.run(*M, MFAM)));
// Check first machine module pass
EXPECT_EQ(1u, TestMachineModuleCount[0].size());
EXPECT_EQ(3, TestMachineModuleCount[0][0]);
// Check first machine function pass
EXPECT_EQ(1u, BeforeInitialization[0].size());
EXPECT_EQ(1, BeforeInitialization[0][0]);
EXPECT_EQ(3u, TestMachineFunctionCount[0].size());
EXPECT_EQ(10, TestMachineFunctionCount[0][0]);
EXPECT_EQ(13, TestMachineFunctionCount[0][1]);
EXPECT_EQ(16, TestMachineFunctionCount[0][2]);
EXPECT_EQ(1u, BeforeFinalization[0].size());
EXPECT_EQ(31, BeforeFinalization[0][0]);
// Check second machine module pass
EXPECT_EQ(1u, TestMachineModuleCount[1].size());
EXPECT_EQ(17, TestMachineModuleCount[1][0]);
// Check second machine function pass
EXPECT_EQ(1u, BeforeInitialization[1].size());
EXPECT_EQ(2, BeforeInitialization[1][0]);
EXPECT_EQ(3u, TestMachineFunctionCount[1].size());
EXPECT_EQ(24, TestMachineFunctionCount[1][0]);
EXPECT_EQ(27, TestMachineFunctionCount[1][1]);
EXPECT_EQ(30, TestMachineFunctionCount[1][2]);
EXPECT_EQ(1u, BeforeFinalization[1].size());
EXPECT_EQ(32, BeforeFinalization[1][0]);
EXPECT_EQ(32, Count);
// doInitialization returns error
Count = 10000;
MFPM.addPass(TestMachineFunctionPass(Count, BeforeInitialization[1],
BeforeFinalization[1],
TestMachineFunctionCount[1]));
std::string Message;
llvm::handleAllErrors(MFPM.run(*M, MFAM), [&](llvm::StringError &Error) {
Message = Error.getMessage();
});
EXPECT_EQ(Message, DoInitErrMsg);
// doFinalization returns error
Count = 1000;
MFPM.addPass(TestMachineFunctionPass(Count, BeforeInitialization[1],
BeforeFinalization[1],
TestMachineFunctionCount[1]));
llvm::handleAllErrors(MFPM.run(*M, MFAM), [&](llvm::StringError &Error) {
Message = Error.getMessage();
});
EXPECT_EQ(Message, DoFinalErrMsg);
}
} // namespace