mirror of
https://github.com/Gericom/teak-llvm.git
synced 2025-06-30 00:38:54 -04:00

a module-specific interface. This is the first of many steps necessary to generalize the infrastructure such that we can support both a Module-to-Function and Module-to-SCC-to-Function pass manager nestings. After a *lot* of attempts that never worked and didn't even make it to a committable state, it became clear that I had gotten the layering design of analyses flat out wrong. Four days later, I think I have most of the plan for how to correct this, and I'm starting to reshape the code into it. This is just a baby step I'm afraid, but starts separating the fundamentally distinct concepts of function analysis passes and module analysis passes so that in subsequent steps we can effectively layer them, and have a consistent design for the eventual SCC layer. As part of this, I've started some interface changes to make passes more regular. The module pass accepts the module in the run method, and some of the constructor parameters are gone. I'm still working out exactly where constructor parameters vs. method parameters will be used, so I expect this to fluctuate a bit. This actually makes the invalidation less "correct" at this phase, because now function passes don't invalidate module analysis passes, but that was actually somewhat of a misfeature. It will return in a better factored form which can scale to other units of IR. The documentation has gotten less verbose and helpful. llvm-svn: 195189
131 lines
3.2 KiB
C++
131 lines
3.2 KiB
C++
//===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Assembly/Parser.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/LLVMContext.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/PassManager.h"
|
|
#include "llvm/Support/SourceMgr.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
using namespace llvm;
|
|
|
|
namespace {
|
|
|
|
class TestAnalysisPass {
|
|
public:
|
|
typedef Function IRUnitT;
|
|
|
|
struct Result {
|
|
Result(int Count) : InstructionCount(Count) {}
|
|
bool invalidate(Function *) { return true; }
|
|
int InstructionCount;
|
|
};
|
|
|
|
/// \brief Returns an opaque, unique ID for this pass type.
|
|
static void *ID() { return (void *)&PassID; }
|
|
|
|
/// \brief Run the analysis pass over the function and return a result.
|
|
Result run(Function *F) {
|
|
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:
|
|
/// \brief Private static data to provide unique ID.
|
|
static char PassID;
|
|
};
|
|
|
|
char TestAnalysisPass::PassID;
|
|
|
|
struct TestModulePass {
|
|
TestModulePass(int &RunCount) : RunCount(RunCount) {}
|
|
|
|
bool run(Module *M) {
|
|
++RunCount;
|
|
return true;
|
|
}
|
|
|
|
int &RunCount;
|
|
};
|
|
|
|
struct TestFunctionPass {
|
|
TestFunctionPass(FunctionAnalysisManager &AM, int &RunCount,
|
|
int &AnalyzedInstrCount)
|
|
: AM(AM), RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount) {}
|
|
|
|
bool run(Function *F) {
|
|
++RunCount;
|
|
|
|
const TestAnalysisPass::Result &AR = AM.getResult<TestAnalysisPass>(F);
|
|
AnalyzedInstrCount += AR.InstructionCount;
|
|
|
|
return true;
|
|
}
|
|
|
|
FunctionAnalysisManager &AM;
|
|
int &RunCount;
|
|
int &AnalyzedInstrCount;
|
|
};
|
|
|
|
Module *parseIR(const char *IR) {
|
|
LLVMContext &C = getGlobalContext();
|
|
SMDiagnostic Err;
|
|
return ParseAssemblyString(IR, 0, Err, C);
|
|
}
|
|
|
|
class PassManagerTest : public ::testing::Test {
|
|
protected:
|
|
OwningPtr<Module> M;
|
|
|
|
public:
|
|
PassManagerTest()
|
|
: M(parseIR("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")) {}
|
|
};
|
|
|
|
TEST_F(PassManagerTest, Basic) {
|
|
FunctionAnalysisManager AM;
|
|
AM.registerPass(TestAnalysisPass());
|
|
|
|
ModulePassManager MPM;
|
|
FunctionPassManager FPM(&AM);
|
|
|
|
// Count the runs over a module.
|
|
int ModulePassRunCount = 0;
|
|
MPM.addPass(TestModulePass(ModulePassRunCount));
|
|
|
|
// Count the runs over a Function.
|
|
int FunctionPassRunCount = 0;
|
|
int AnalyzedInstrCount = 0;
|
|
FPM.addPass(TestFunctionPass(AM, FunctionPassRunCount, AnalyzedInstrCount));
|
|
MPM.addPass(FPM);
|
|
|
|
MPM.run(M.get());
|
|
EXPECT_EQ(1, ModulePassRunCount);
|
|
EXPECT_EQ(3, FunctionPassRunCount);
|
|
EXPECT_EQ(5, AnalyzedInstrCount);
|
|
}
|
|
}
|