summaryrefslogtreecommitdiff
path: root/unittests/IR
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-12-22 00:04:03 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-12-22 00:04:03 +0000
commitf8af5cf600354830d4ccf59732403f0f073eccb9 (patch)
tree2ba0398b4c42ad4f55561327538044fd2c925a8b /unittests/IR
parent59d6cff90eecf31cb3dd860c4e786674cfdd42eb (diff)
Notes
Diffstat (limited to 'unittests/IR')
-rw-r--r--unittests/IR/AttributesTest.cpp13
-rw-r--r--unittests/IR/CMakeLists.txt1
-rw-r--r--unittests/IR/IRBuilderTest.cpp55
-rw-r--r--unittests/IR/InstructionsTest.cpp146
-rw-r--r--unittests/IR/LegacyPassManagerTest.cpp559
-rw-r--r--unittests/IR/PassManagerTest.cpp625
-rw-r--r--unittests/IR/ValueTest.cpp40
-rw-r--r--unittests/IR/VerifierTest.cpp23
-rw-r--r--unittests/IR/WaymarkTest.cpp1
9 files changed, 918 insertions, 545 deletions
diff --git a/unittests/IR/AttributesTest.cpp b/unittests/IR/AttributesTest.cpp
index 2368bdf94dc43..ebcb772bc3739 100644
--- a/unittests/IR/AttributesTest.cpp
+++ b/unittests/IR/AttributesTest.cpp
@@ -31,4 +31,17 @@ TEST(Attributes, Uniquing) {
EXPECT_EQ(SetA, SetB);
}
+TEST(Attributes, Ordering) {
+ LLVMContext C;
+
+ AttributeSet ASs[] = {
+ AttributeSet::get(C, 2, Attribute::ZExt),
+ AttributeSet::get(C, 1, Attribute::SExt)
+ };
+
+ AttributeSet SetA = AttributeSet::get(C, ASs);
+ AttributeSet SetB = SetA.removeAttributes(C, 1, ASs[1]);
+ EXPECT_NE(SetA, SetB);
+}
+
} // end anonymous namespace
diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt
index c53043ef80e11..fd0831f8e1fa1 100644
--- a/unittests/IR/CMakeLists.txt
+++ b/unittests/IR/CMakeLists.txt
@@ -10,6 +10,7 @@ set(IRSources
DominatorTreeTest.cpp
IRBuilderTest.cpp
InstructionsTest.cpp
+ LegacyPassManagerTest.cpp
MDBuilderTest.cpp
MetadataTest.cpp
PassManagerTest.cpp
diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp
index fecc4a4fe6b41..2f390f7f75a2f 100644
--- a/unittests/IR/IRBuilderTest.cpp
+++ b/unittests/IR/IRBuilderTest.cpp
@@ -25,12 +25,12 @@ namespace {
class IRBuilderTest : public testing::Test {
protected:
virtual void SetUp() {
- M.reset(new Module("MyModule", getGlobalContext()));
- FunctionType *FTy = FunctionType::get(Type::getVoidTy(getGlobalContext()),
+ M.reset(new Module("MyModule", Ctx));
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
/*isVarArg=*/false);
F = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
- BB = BasicBlock::Create(getGlobalContext(), "", F);
- GV = new GlobalVariable(*M, Type::getFloatTy(getGlobalContext()), true,
+ BB = BasicBlock::Create(Ctx, "", F);
+ GV = new GlobalVariable(*M, Type::getFloatTy(Ctx), true,
GlobalValue::ExternalLinkage, 0);
}
@@ -39,6 +39,7 @@ protected:
M.reset();
}
+ LLVMContext Ctx;
OwningPtr<Module> M;
Function *F;
BasicBlock *BB;
@@ -78,8 +79,8 @@ TEST_F(IRBuilderTest, Lifetime) {
TEST_F(IRBuilderTest, CreateCondBr) {
IRBuilder<> Builder(BB);
- BasicBlock *TBB = BasicBlock::Create(getGlobalContext(), "", F);
- BasicBlock *FBB = BasicBlock::Create(getGlobalContext(), "", F);
+ BasicBlock *TBB = BasicBlock::Create(Ctx, "", F);
+ BasicBlock *FBB = BasicBlock::Create(Ctx, "", F);
BranchInst *BI = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
TerminatorInst *TI = BB->getTerminator();
@@ -89,7 +90,7 @@ TEST_F(IRBuilderTest, CreateCondBr) {
EXPECT_EQ(FBB, TI->getSuccessor(1));
BI->eraseFromParent();
- MDNode *Weights = MDBuilder(getGlobalContext()).createBranchWeights(42, 13);
+ MDNode *Weights = MDBuilder(Ctx).createBranchWeights(42, 13);
BI = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB, Weights);
TI = BB->getTerminator();
EXPECT_EQ(BI, TI);
@@ -109,12 +110,12 @@ TEST_F(IRBuilderTest, LandingPadName) {
TEST_F(IRBuilderTest, GetIntTy) {
IRBuilder<> Builder(BB);
IntegerType *Ty1 = Builder.getInt1Ty();
- EXPECT_EQ(Ty1, IntegerType::get(getGlobalContext(), 1));
+ EXPECT_EQ(Ty1, IntegerType::get(Ctx, 1));
DataLayout* DL = new DataLayout(M.get());
IntegerType *IntPtrTy = Builder.getIntPtrTy(DL);
unsigned IntPtrBitSize = DL->getPointerSizeInBits(0);
- EXPECT_EQ(IntPtrTy, IntegerType::get(getGlobalContext(), IntPtrBitSize));
+ EXPECT_EQ(IntPtrTy, IntegerType::get(Ctx, IntPtrBitSize));
delete DL;
}
@@ -182,4 +183,40 @@ TEST_F(IRBuilderTest, FastMathFlags) {
}
+TEST_F(IRBuilderTest, RAIIHelpersTest) {
+ IRBuilder<> Builder(BB);
+ EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal());
+ MDBuilder MDB(M->getContext());
+
+ MDNode *FPMathA = MDB.createFPMath(0.01f);
+ MDNode *FPMathB = MDB.createFPMath(0.1f);
+
+ Builder.SetDefaultFPMathTag(FPMathA);
+
+ {
+ IRBuilder<>::FastMathFlagGuard Guard(Builder);
+ FastMathFlags FMF;
+ FMF.setAllowReciprocal();
+ Builder.SetFastMathFlags(FMF);
+ Builder.SetDefaultFPMathTag(FPMathB);
+ EXPECT_TRUE(Builder.getFastMathFlags().allowReciprocal());
+ EXPECT_EQ(FPMathB, Builder.getDefaultFPMathTag());
+ }
+
+ EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal());
+ EXPECT_EQ(FPMathA, Builder.getDefaultFPMathTag());
+
+ Value *F = Builder.CreateLoad(GV);
+
+ {
+ IRBuilder<>::InsertPointGuard Guard(Builder);
+ Builder.SetInsertPoint(cast<Instruction>(F));
+ EXPECT_EQ(F, Builder.GetInsertPoint());
+ }
+
+ EXPECT_EQ(BB->end(), Builder.GetInsertPoint());
+ EXPECT_EQ(BB, Builder.GetInsertBlock());
+}
+
+
}
diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp
index 9f66af147180e..65f85ba1b7079 100644
--- a/unittests/IR/InstructionsTest.cpp
+++ b/unittests/IR/InstructionsTest.cpp
@@ -116,15 +116,41 @@ TEST(InstructionsTest, BranchInst) {
TEST(InstructionsTest, CastInst) {
LLVMContext &C(getGlobalContext());
- Type* Int8Ty = Type::getInt8Ty(C);
- Type* Int64Ty = Type::getInt64Ty(C);
- Type* V8x8Ty = VectorType::get(Int8Ty, 8);
- Type* V8x64Ty = VectorType::get(Int64Ty, 8);
- Type* X86MMXTy = Type::getX86_MMXTy(C);
+ Type *Int8Ty = Type::getInt8Ty(C);
+ Type *Int16Ty = Type::getInt16Ty(C);
+ Type *Int32Ty = Type::getInt32Ty(C);
+ Type *Int64Ty = Type::getInt64Ty(C);
+ Type *V8x8Ty = VectorType::get(Int8Ty, 8);
+ Type *V8x64Ty = VectorType::get(Int64Ty, 8);
+ Type *X86MMXTy = Type::getX86_MMXTy(C);
+
+ Type *HalfTy = Type::getHalfTy(C);
+ Type *FloatTy = Type::getFloatTy(C);
+ Type *DoubleTy = Type::getDoubleTy(C);
+
+ Type *V2Int32Ty = VectorType::get(Int32Ty, 2);
+ Type *V2Int64Ty = VectorType::get(Int64Ty, 2);
+ Type *V4Int16Ty = VectorType::get(Int16Ty, 4);
+
+ Type *Int32PtrTy = PointerType::get(Int32Ty, 0);
+ Type *Int64PtrTy = PointerType::get(Int64Ty, 0);
+
+ Type *Int32PtrAS1Ty = PointerType::get(Int32Ty, 1);
+ Type *Int64PtrAS1Ty = PointerType::get(Int64Ty, 1);
+
+ Type *V2Int32PtrAS1Ty = VectorType::get(Int32PtrAS1Ty, 2);
+ Type *V2Int64PtrAS1Ty = VectorType::get(Int64PtrAS1Ty, 2);
+ Type *V4Int32PtrAS1Ty = VectorType::get(Int32PtrAS1Ty, 4);
+ Type *V4Int64PtrAS1Ty = VectorType::get(Int64PtrAS1Ty, 4);
+
+ Type *V2Int64PtrTy = VectorType::get(Int64PtrTy, 2);
+ Type *V2Int32PtrTy = VectorType::get(Int32PtrTy, 2);
const Constant* c8 = Constant::getNullValue(V8x8Ty);
const Constant* c64 = Constant::getNullValue(V8x64Ty);
+ const Constant *v2ptr32 = Constant::getNullValue(V2Int32PtrTy);
+
EXPECT_TRUE(CastInst::isCastable(V8x8Ty, X86MMXTy));
EXPECT_TRUE(CastInst::isCastable(X86MMXTy, V8x8Ty));
EXPECT_FALSE(CastInst::isCastable(Int64Ty, X86MMXTy));
@@ -132,16 +158,70 @@ TEST(InstructionsTest, CastInst) {
EXPECT_TRUE(CastInst::isCastable(V8x8Ty, V8x64Ty));
EXPECT_EQ(CastInst::Trunc, CastInst::getCastOpcode(c64, true, V8x8Ty, true));
EXPECT_EQ(CastInst::SExt, CastInst::getCastOpcode(c8, true, V8x64Ty, true));
-}
-
+ EXPECT_FALSE(CastInst::isBitCastable(V8x8Ty, X86MMXTy));
+ EXPECT_FALSE(CastInst::isBitCastable(X86MMXTy, V8x8Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, X86MMXTy));
+ EXPECT_FALSE(CastInst::isBitCastable(V8x64Ty, V8x8Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(V8x8Ty, V8x64Ty));
+
+ // Check address space casts are rejected since we don't know the sizes here
+ EXPECT_FALSE(CastInst::isBitCastable(Int32PtrTy, Int32PtrAS1Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int32PtrAS1Ty, Int32PtrTy));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, V2Int32PtrAS1Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int32PtrTy));
+ EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int64PtrAS1Ty));
+ EXPECT_TRUE(CastInst::isCastable(V2Int32PtrAS1Ty, V2Int32PtrTy));
+ EXPECT_EQ(CastInst::AddrSpaceCast, CastInst::getCastOpcode(v2ptr32, true,
+ V2Int32PtrAS1Ty,
+ true));
+
+ // Test mismatched number of elements for pointers
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int64PtrAS1Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(V4Int64PtrAS1Ty, V2Int32PtrAS1Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int32PtrAS1Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int32PtrTy, V2Int32PtrTy));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, Int32PtrTy));
+
+ EXPECT_TRUE(CastInst::isBitCastable(Int32PtrTy, Int64PtrTy));
+ EXPECT_FALSE(CastInst::isBitCastable(DoubleTy, FloatTy));
+ EXPECT_FALSE(CastInst::isBitCastable(FloatTy, DoubleTy));
+ EXPECT_TRUE(CastInst::isBitCastable(FloatTy, FloatTy));
+ EXPECT_TRUE(CastInst::isBitCastable(FloatTy, FloatTy));
+ EXPECT_TRUE(CastInst::isBitCastable(FloatTy, Int32Ty));
+ EXPECT_TRUE(CastInst::isBitCastable(Int16Ty, HalfTy));
+ EXPECT_TRUE(CastInst::isBitCastable(Int32Ty, FloatTy));
+ EXPECT_TRUE(CastInst::isBitCastable(V2Int32Ty, Int64Ty));
+
+ EXPECT_TRUE(CastInst::isBitCastable(V2Int32Ty, V4Int16Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int32Ty, Int64Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, Int32Ty));
+
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, Int64Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, V2Int32PtrTy));
+ EXPECT_TRUE(CastInst::isBitCastable(V2Int64PtrTy, V2Int32PtrTy));
+ EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrTy, V2Int64PtrTy));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32Ty, V2Int64Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int64Ty, V2Int32Ty));
+
+
+ // Check that assertion is not hit when creating a cast with a vector of
+ // pointers
+ // First form
+ BasicBlock *BB = BasicBlock::Create(C);
+ Constant *NullV2I32Ptr = Constant::getNullValue(V2Int32PtrTy);
+ CastInst::CreatePointerCast(NullV2I32Ptr, V2Int32Ty, "foo", BB);
+
+ // Second form
+ CastInst::CreatePointerCast(NullV2I32Ptr, V2Int32Ty);
+}
TEST(InstructionsTest, VectorGep) {
LLVMContext &C(getGlobalContext());
// Type Definitions
PointerType *Ptri8Ty = PointerType::get(IntegerType::get(C, 8), 0);
- PointerType *Ptri32Ty = PointerType::get(IntegerType::get(C, 8), 0);
+ PointerType *Ptri32Ty = PointerType::get(IntegerType::get(C, 32), 0);
VectorType *V2xi8PTy = VectorType::get(Ptri8Ty, 2);
VectorType *V2xi32PTy = VectorType::get(Ptri32Ty, 2);
@@ -255,6 +335,7 @@ TEST(InstructionsTest, FPMathOperator) {
TEST(InstructionsTest, isEliminableCastPair) {
LLVMContext &C(getGlobalContext());
+ Type* Int16Ty = Type::getInt16Ty(C);
Type* Int32Ty = Type::getInt32Ty(C);
Type* Int64Ty = Type::getInt64Ty(C);
Type* Int64PtrTy = Type::getInt64PtrTy(C);
@@ -266,11 +347,20 @@ TEST(InstructionsTest, isEliminableCastPair) {
Int32Ty, 0, Int32Ty),
CastInst::BitCast);
- // Source and destination pointers have different sizes -> fail.
+ // Source and destination have unknown sizes, but the same address space and
+ // the intermediate int is the maximum pointer size -> bitcast
EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt,
CastInst::IntToPtr,
Int64PtrTy, Int64Ty, Int64PtrTy,
- Int32Ty, 0, Int64Ty),
+ 0, 0, 0),
+ CastInst::BitCast);
+
+ // Source and destination have unknown sizes, but the same address space and
+ // the intermediate int is not the maximum pointer size -> nothing
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt,
+ CastInst::IntToPtr,
+ Int64PtrTy, Int32Ty, Int64PtrTy,
+ 0, 0, 0),
0U);
// Middle pointer big enough -> bitcast.
@@ -286,7 +376,43 @@ TEST(InstructionsTest, isEliminableCastPair) {
Int64Ty, Int64PtrTy, Int64Ty,
0, Int32Ty, 0),
0U);
+
+ // Test that we don't eliminate bitcasts between different address spaces,
+ // or if we don't have available pointer size information.
+ DataLayout DL("e-p:32:32:32-p1:16:16:16-p2:64:64:64-i1:8:8-i8:8:8-i16:16:16"
+ "-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64"
+ "-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128");
+
+ Type* Int64PtrTyAS1 = Type::getInt64PtrTy(C, 1);
+ Type* Int64PtrTyAS2 = Type::getInt64PtrTy(C, 2);
+
+ IntegerType *Int16SizePtr = DL.getIntPtrType(C, 1);
+ IntegerType *Int64SizePtr = DL.getIntPtrType(C, 2);
+
+ // Cannot simplify inttoptr, addrspacecast
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::AddrSpaceCast,
+ Int16Ty, Int64PtrTyAS1, Int64PtrTyAS2,
+ 0, Int16SizePtr, Int64SizePtr),
+ 0U);
+
+ // Cannot simplify addrspacecast, ptrtoint
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::AddrSpaceCast,
+ CastInst::PtrToInt,
+ Int64PtrTyAS1, Int64PtrTyAS2, Int16Ty,
+ Int64SizePtr, Int16SizePtr, 0),
+ 0U);
+
+ // Pass since the bitcast address spaces are the same
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::BitCast,
+ Int16Ty, Int64PtrTyAS1, Int64PtrTyAS1,
+ 0, 0, 0),
+ CastInst::IntToPtr);
+
}
} // end anonymous namespace
} // end namespace llvm
+
+
diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp
new file mode 100644
index 0000000000000..11841bdeac0dd
--- /dev/null
+++ b/unittests/IR/LegacyPassManagerTest.cpp
@@ -0,0 +1,559 @@
+//===- llvm/unittest/IR/LegacyPassManager.cpp - Legacy PassManager tests --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This unit test exercises the legacy pass manager infrastructure. We use the
+// old names as well to ensure that the source-level compatibility wrapper
+// works for out-of-tree code that expects to include llvm/PassManager.h and
+// subclass the core pass classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/PassManager.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/CallGraphSCCPass.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/Analysis/Verifier.h"
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace llvm {
+ void initializeModuleNDMPass(PassRegistry&);
+ void initializeFPassPass(PassRegistry&);
+ void initializeCGPassPass(PassRegistry&);
+ void initializeLPassPass(PassRegistry&);
+ void initializeBPassPass(PassRegistry&);
+
+ namespace {
+ // ND = no deps
+ // NM = no modifications
+ struct ModuleNDNM: public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleNDNM() : ModulePass(ID) { }
+ virtual bool runOnModule(Module &M) {
+ run++;
+ return false;
+ }
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ }
+ };
+ char ModuleNDNM::ID=0;
+ char ModuleNDNM::run=0;
+
+ struct ModuleNDM : public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleNDM() : ModulePass(ID) {}
+ virtual bool runOnModule(Module &M) {
+ run++;
+ return true;
+ }
+ };
+ char ModuleNDM::ID=0;
+ char ModuleNDM::run=0;
+
+ struct ModuleNDM2 : public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleNDM2() : ModulePass(ID) {}
+ virtual bool runOnModule(Module &M) {
+ run++;
+ return true;
+ }
+ };
+ char ModuleNDM2::ID=0;
+ char ModuleNDM2::run=0;
+
+ struct ModuleDNM : public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleDNM() : ModulePass(ID) {
+ initializeModuleNDMPass(*PassRegistry::getPassRegistry());
+ }
+ virtual bool runOnModule(Module &M) {
+ EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run++;
+ return false;
+ }
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<ModuleNDM>();
+ AU.setPreservesAll();
+ }
+ };
+ char ModuleDNM::ID=0;
+ char ModuleDNM::run=0;
+
+ template<typename P>
+ struct PassTestBase : public P {
+ protected:
+ static int runc;
+ static bool initialized;
+ static bool finalized;
+ int allocated;
+ void run() {
+ EXPECT_TRUE(initialized);
+ EXPECT_FALSE(finalized);
+ EXPECT_EQ(0, allocated);
+ allocated++;
+ runc++;
+ }
+ public:
+ static char ID;
+ static void finishedOK(int run) {
+ EXPECT_GT(runc, 0);
+ EXPECT_TRUE(initialized);
+ EXPECT_TRUE(finalized);
+ EXPECT_EQ(run, runc);
+ }
+ PassTestBase() : P(ID), allocated(0) {
+ initialized = false;
+ finalized = false;
+ runc = 0;
+ }
+
+ virtual void releaseMemory() {
+ EXPECT_GT(runc, 0);
+ EXPECT_GT(allocated, 0);
+ allocated--;
+ }
+ };
+ template<typename P> char PassTestBase<P>::ID;
+ template<typename P> int PassTestBase<P>::runc;
+ template<typename P> bool PassTestBase<P>::initialized;
+ template<typename P> bool PassTestBase<P>::finalized;
+
+ template<typename T, typename P>
+ struct PassTest : public PassTestBase<P> {
+ public:
+#ifndef _MSC_VER // MSVC complains that Pass is not base class.
+ using llvm::Pass::doInitialization;
+ using llvm::Pass::doFinalization;
+#endif
+ virtual bool doInitialization(T &t) {
+ EXPECT_FALSE(PassTestBase<P>::initialized);
+ PassTestBase<P>::initialized = true;
+ return false;
+ }
+ virtual bool doFinalization(T &t) {
+ EXPECT_FALSE(PassTestBase<P>::finalized);
+ PassTestBase<P>::finalized = true;
+ EXPECT_EQ(0, PassTestBase<P>::allocated);
+ return false;
+ }
+ };
+
+ struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> {
+ public:
+ CGPass() {
+ initializeCGPassPass(*PassRegistry::getPassRegistry());
+ }
+ virtual bool runOnSCC(CallGraphSCC &SCMM) {
+ EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run();
+ return false;
+ }
+ };
+
+ struct FPass : public PassTest<Module, FunctionPass> {
+ public:
+ virtual bool runOnFunction(Function &F) {
+ // FIXME: PR4112
+ // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run();
+ return false;
+ }
+ };
+
+ struct LPass : public PassTestBase<LoopPass> {
+ private:
+ static int initcount;
+ static int fincount;
+ public:
+ LPass() {
+ initializeLPassPass(*PassRegistry::getPassRegistry());
+ initcount = 0; fincount=0;
+ EXPECT_FALSE(initialized);
+ }
+ static void finishedOK(int run, int finalized) {
+ PassTestBase<LoopPass>::finishedOK(run);
+ EXPECT_EQ(run, initcount);
+ EXPECT_EQ(finalized, fincount);
+ }
+ using llvm::Pass::doInitialization;
+ using llvm::Pass::doFinalization;
+ virtual bool doInitialization(Loop* L, LPPassManager &LPM) {
+ initialized = true;
+ initcount++;
+ return false;
+ }
+ virtual bool runOnLoop(Loop *L, LPPassManager &LPM) {
+ EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run();
+ return false;
+ }
+ virtual bool doFinalization() {
+ fincount++;
+ finalized = true;
+ return false;
+ }
+ };
+ int LPass::initcount=0;
+ int LPass::fincount=0;
+
+ struct BPass : public PassTestBase<BasicBlockPass> {
+ private:
+ static int inited;
+ static int fin;
+ public:
+ static void finishedOK(int run, int N) {
+ PassTestBase<BasicBlockPass>::finishedOK(run);
+ EXPECT_EQ(inited, N);
+ EXPECT_EQ(fin, N);
+ }
+ BPass() {
+ inited = 0;
+ fin = 0;
+ }
+ virtual bool doInitialization(Module &M) {
+ EXPECT_FALSE(initialized);
+ initialized = true;
+ return false;
+ }
+ virtual bool doInitialization(Function &F) {
+ inited++;
+ return false;
+ }
+ virtual bool runOnBasicBlock(BasicBlock &BB) {
+ EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run();
+ return false;
+ }
+ virtual bool doFinalization(Function &F) {
+ fin++;
+ return false;
+ }
+ virtual bool doFinalization(Module &M) {
+ EXPECT_FALSE(finalized);
+ finalized = true;
+ EXPECT_EQ(0, allocated);
+ return false;
+ }
+ };
+ int BPass::inited=0;
+ int BPass::fin=0;
+
+ struct OnTheFlyTest: public ModulePass {
+ public:
+ static char ID;
+ OnTheFlyTest() : ModulePass(ID) {
+ initializeFPassPass(*PassRegistry::getPassRegistry());
+ }
+ virtual bool runOnModule(Module &M) {
+ EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) {
+ Function &F = *I;
+ {
+ SCOPED_TRACE("Running on the fly function pass");
+ getAnalysis<FPass>(F);
+ }
+ }
+ return false;
+ }
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<FPass>();
+ }
+ };
+ char OnTheFlyTest::ID=0;
+
+ TEST(PassManager, RunOnce) {
+ Module M("test-once", getGlobalContext());
+ struct ModuleNDNM *mNDNM = new ModuleNDNM();
+ struct ModuleDNM *mDNM = new ModuleDNM();
+ struct ModuleNDM *mNDM = new ModuleNDM();
+ struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
+
+ mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
+
+ PassManager Passes;
+ Passes.add(new DataLayout(&M));
+ Passes.add(mNDM2);
+ Passes.add(mNDM);
+ Passes.add(mNDNM);
+ Passes.add(mDNM);
+
+ Passes.run(M);
+ // each pass must be run exactly once, since nothing invalidates them
+ EXPECT_EQ(1, mNDM->run);
+ EXPECT_EQ(1, mNDNM->run);
+ EXPECT_EQ(1, mDNM->run);
+ EXPECT_EQ(1, mNDM2->run);
+ }
+
+ TEST(PassManager, ReRun) {
+ Module M("test-rerun", getGlobalContext());
+ struct ModuleNDNM *mNDNM = new ModuleNDNM();
+ struct ModuleDNM *mDNM = new ModuleDNM();
+ struct ModuleNDM *mNDM = new ModuleNDM();
+ struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
+
+ mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
+
+ PassManager Passes;
+ Passes.add(new DataLayout(&M));
+ Passes.add(mNDM);
+ Passes.add(mNDNM);
+ Passes.add(mNDM2);// invalidates mNDM needed by mDNM
+ Passes.add(mDNM);
+
+ Passes.run(M);
+ // Some passes must be rerun because a pass that modified the
+ // module/function was run in between
+ EXPECT_EQ(2, mNDM->run);
+ EXPECT_EQ(1, mNDNM->run);
+ EXPECT_EQ(1, mNDM2->run);
+ EXPECT_EQ(1, mDNM->run);
+ }
+
+ Module* makeLLVMModule();
+
+ template<typename T>
+ void MemoryTestHelper(int run) {
+ OwningPtr<Module> M(makeLLVMModule());
+ T *P = new T();
+ PassManager Passes;
+ Passes.add(new DataLayout(M.get()));
+ Passes.add(P);
+ Passes.run(*M);
+ T::finishedOK(run);
+ }
+
+ template<typename T>
+ void MemoryTestHelper(int run, int N) {
+ Module *M = makeLLVMModule();
+ T *P = new T();
+ PassManager Passes;
+ Passes.add(new DataLayout(M));
+ Passes.add(P);
+ Passes.run(*M);
+ T::finishedOK(run, N);
+ delete M;
+ }
+
+ TEST(PassManager, Memory) {
+ // SCC#1: test1->test2->test3->test1
+ // SCC#2: test4
+ // SCC#3: indirect call node
+ {
+ SCOPED_TRACE("Callgraph pass");
+ MemoryTestHelper<CGPass>(3);
+ }
+
+ {
+ SCOPED_TRACE("Function pass");
+ MemoryTestHelper<FPass>(4);// 4 functions
+ }
+
+ {
+ SCOPED_TRACE("Loop pass");
+ MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function
+ }
+ {
+ SCOPED_TRACE("Basic block pass");
+ MemoryTestHelper<BPass>(7, 4); //9 basic blocks
+ }
+
+ }
+
+ TEST(PassManager, MemoryOnTheFly) {
+ Module *M = makeLLVMModule();
+ {
+ SCOPED_TRACE("Running OnTheFlyTest");
+ struct OnTheFlyTest *O = new OnTheFlyTest();
+ PassManager Passes;
+ Passes.add(new DataLayout(M));
+ Passes.add(O);
+ Passes.run(*M);
+
+ FPass::finishedOK(4);
+ }
+ delete M;
+ }
+
+ Module* makeLLVMModule() {
+ // Module Construction
+ Module* mod = new Module("test-mem", getGlobalContext());
+ mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
+ "a0:0:64-s0:64:64-f80:128:128");
+ mod->setTargetTriple("x86_64-unknown-linux-gnu");
+
+ // Type Definitions
+ std::vector<Type*>FuncTy_0_args;
+ FunctionType* FuncTy_0 = FunctionType::get(
+ /*Result=*/IntegerType::get(getGlobalContext(), 32),
+ /*Params=*/FuncTy_0_args,
+ /*isVarArg=*/false);
+
+ std::vector<Type*>FuncTy_2_args;
+ FuncTy_2_args.push_back(IntegerType::get(getGlobalContext(), 1));
+ FunctionType* FuncTy_2 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(getGlobalContext()),
+ /*Params=*/FuncTy_2_args,
+ /*isVarArg=*/false);
+
+
+ // Function Declarations
+
+ Function* func_test1 = Function::Create(
+ /*Type=*/FuncTy_0,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test1", mod);
+ func_test1->setCallingConv(CallingConv::C);
+ AttributeSet func_test1_PAL;
+ func_test1->setAttributes(func_test1_PAL);
+
+ Function* func_test2 = Function::Create(
+ /*Type=*/FuncTy_0,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test2", mod);
+ func_test2->setCallingConv(CallingConv::C);
+ AttributeSet func_test2_PAL;
+ func_test2->setAttributes(func_test2_PAL);
+
+ Function* func_test3 = Function::Create(
+ /*Type=*/FuncTy_0,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test3", mod);
+ func_test3->setCallingConv(CallingConv::C);
+ AttributeSet func_test3_PAL;
+ func_test3->setAttributes(func_test3_PAL);
+
+ Function* func_test4 = Function::Create(
+ /*Type=*/FuncTy_2,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test4", mod);
+ func_test4->setCallingConv(CallingConv::C);
+ AttributeSet func_test4_PAL;
+ func_test4->setAttributes(func_test4_PAL);
+
+ // Global Variable Declarations
+
+
+ // Constant Definitions
+
+ // Global Variable Definitions
+
+ // Function Definitions
+
+ // Function: test1 (func_test1)
+ {
+
+ BasicBlock* label_entry = BasicBlock::Create(getGlobalContext(), "entry",func_test1,0);
+
+ // Block entry (label_entry)
+ CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry);
+ int32_3->setCallingConv(CallingConv::C);
+ int32_3->setTailCall(false);AttributeSet int32_3_PAL;
+ int32_3->setAttributes(int32_3_PAL);
+
+ ReturnInst::Create(getGlobalContext(), int32_3, label_entry);
+
+ }
+
+ // Function: test2 (func_test2)
+ {
+
+ BasicBlock* label_entry_5 = BasicBlock::Create(getGlobalContext(), "entry",func_test2,0);
+
+ // Block entry (label_entry_5)
+ CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5);
+ int32_6->setCallingConv(CallingConv::C);
+ int32_6->setTailCall(false);AttributeSet int32_6_PAL;
+ int32_6->setAttributes(int32_6_PAL);
+
+ ReturnInst::Create(getGlobalContext(), int32_6, label_entry_5);
+
+ }
+
+ // Function: test3 (func_test3)
+ {
+
+ BasicBlock* label_entry_8 = BasicBlock::Create(getGlobalContext(), "entry",func_test3,0);
+
+ // Block entry (label_entry_8)
+ CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8);
+ int32_9->setCallingConv(CallingConv::C);
+ int32_9->setTailCall(false);AttributeSet int32_9_PAL;
+ int32_9->setAttributes(int32_9_PAL);
+
+ ReturnInst::Create(getGlobalContext(), int32_9, label_entry_8);
+
+ }
+
+ // Function: test4 (func_test4)
+ {
+ Function::arg_iterator args = func_test4->arg_begin();
+ Value* int1_f = args++;
+ int1_f->setName("f");
+
+ BasicBlock* label_entry_11 = BasicBlock::Create(getGlobalContext(), "entry",func_test4,0);
+ BasicBlock* label_bb = BasicBlock::Create(getGlobalContext(), "bb",func_test4,0);
+ BasicBlock* label_bb1 = BasicBlock::Create(getGlobalContext(), "bb1",func_test4,0);
+ BasicBlock* label_return = BasicBlock::Create(getGlobalContext(), "return",func_test4,0);
+
+ // Block entry (label_entry_11)
+ BranchInst::Create(label_bb, label_entry_11);
+
+ // Block bb (label_bb)
+ BranchInst::Create(label_bb, label_bb1, int1_f, label_bb);
+
+ // Block bb1 (label_bb1)
+ BranchInst::Create(label_bb1, label_return, int1_f, label_bb1);
+
+ // Block return (label_return)
+ ReturnInst::Create(getGlobalContext(), label_return);
+
+ }
+ return mod;
+ }
+
+ }
+}
+
+INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false)
+INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false)
+INITIALIZE_PASS_DEPENDENCY(CallGraph)
+INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false)
+INITIALIZE_PASS(FPass, "fp","fp", false, false)
+INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false)
+INITIALIZE_PASS_DEPENDENCY(LoopInfo)
+INITIALIZE_PASS_END(LPass, "lp","lp", false, false)
+INITIALIZE_PASS(BPass, "bp","bp", false, false)
diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp
index 1097da61b9d99..7b60e3899a0ef 100644
--- a/unittests/IR/PassManagerTest.cpp
+++ b/unittests/IR/PassManagerTest.cpp
@@ -1,4 +1,4 @@
-//===- llvm/unittest/IR/PassManager.cpp - PassManager unit tests ----------===//
+//===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,546 +7,125 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/PassManager.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Analysis/CallGraphSCCPass.h"
-#include "llvm/Analysis/LoopInfo.h"
-#include "llvm/Analysis/LoopPass.h"
-#include "llvm/Analysis/Verifier.h"
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/IR/BasicBlock.h"
-#include "llvm/IR/CallingConv.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DerivedTypes.h"
+#include "llvm/Assembly/Parser.h"
#include "llvm/IR/Function.h"
-#include "llvm/IR/GlobalVariable.h"
-#include "llvm/IR/InlineAsm.h"
-#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/MathExtras.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
-namespace llvm {
- void initializeModuleNDMPass(PassRegistry&);
- void initializeFPassPass(PassRegistry&);
- void initializeCGPassPass(PassRegistry&);
- void initializeLPassPass(PassRegistry&);
- void initializeBPassPass(PassRegistry&);
-
- namespace {
- // ND = no deps
- // NM = no modifications
- struct ModuleNDNM: public ModulePass {
- public:
- static char run;
- static char ID;
- ModuleNDNM() : ModulePass(ID) { }
- virtual bool runOnModule(Module &M) {
- run++;
- return false;
- }
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- }
- };
- char ModuleNDNM::ID=0;
- char ModuleNDNM::run=0;
-
- struct ModuleNDM : public ModulePass {
- public:
- static char run;
- static char ID;
- ModuleNDM() : ModulePass(ID) {}
- virtual bool runOnModule(Module &M) {
- run++;
- return true;
- }
- };
- char ModuleNDM::ID=0;
- char ModuleNDM::run=0;
-
- struct ModuleNDM2 : public ModulePass {
- public:
- static char run;
- static char ID;
- ModuleNDM2() : ModulePass(ID) {}
- virtual bool runOnModule(Module &M) {
- run++;
- return true;
- }
- };
- char ModuleNDM2::ID=0;
- char ModuleNDM2::run=0;
-
- struct ModuleDNM : public ModulePass {
- public:
- static char run;
- static char ID;
- ModuleDNM() : ModulePass(ID) {
- initializeModuleNDMPass(*PassRegistry::getPassRegistry());
- }
- virtual bool runOnModule(Module &M) {
- EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- run++;
- return false;
- }
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<ModuleNDM>();
- AU.setPreservesAll();
- }
- };
- char ModuleDNM::ID=0;
- char ModuleDNM::run=0;
-
- template<typename P>
- struct PassTestBase : public P {
- protected:
- static int runc;
- static bool initialized;
- static bool finalized;
- int allocated;
- void run() {
- EXPECT_TRUE(initialized);
- EXPECT_FALSE(finalized);
- EXPECT_EQ(0, allocated);
- allocated++;
- runc++;
- }
- public:
- static char ID;
- static void finishedOK(int run) {
- EXPECT_GT(runc, 0);
- EXPECT_TRUE(initialized);
- EXPECT_TRUE(finalized);
- EXPECT_EQ(run, runc);
- }
- PassTestBase() : P(ID), allocated(0) {
- initialized = false;
- finalized = false;
- runc = 0;
- }
-
- virtual void releaseMemory() {
- EXPECT_GT(runc, 0);
- EXPECT_GT(allocated, 0);
- allocated--;
- }
- };
- template<typename P> char PassTestBase<P>::ID;
- template<typename P> int PassTestBase<P>::runc;
- template<typename P> bool PassTestBase<P>::initialized;
- template<typename P> bool PassTestBase<P>::finalized;
-
- template<typename T, typename P>
- struct PassTest : public PassTestBase<P> {
- public:
-#ifndef _MSC_VER // MSVC complains that Pass is not base class.
- using llvm::Pass::doInitialization;
- using llvm::Pass::doFinalization;
-#endif
- virtual bool doInitialization(T &t) {
- EXPECT_FALSE(PassTestBase<P>::initialized);
- PassTestBase<P>::initialized = true;
- return false;
- }
- virtual bool doFinalization(T &t) {
- EXPECT_FALSE(PassTestBase<P>::finalized);
- PassTestBase<P>::finalized = true;
- EXPECT_EQ(0, PassTestBase<P>::allocated);
- return false;
- }
- };
-
- struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> {
- public:
- CGPass() {
- initializeCGPassPass(*PassRegistry::getPassRegistry());
- }
- virtual bool runOnSCC(CallGraphSCC &SCMM) {
- EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- run();
- return false;
- }
- };
-
- struct FPass : public PassTest<Module, FunctionPass> {
- public:
- virtual bool runOnFunction(Function &F) {
- // FIXME: PR4112
- // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- run();
- return false;
- }
- };
-
- struct LPass : public PassTestBase<LoopPass> {
- private:
- static int initcount;
- static int fincount;
- public:
- LPass() {
- initializeLPassPass(*PassRegistry::getPassRegistry());
- initcount = 0; fincount=0;
- EXPECT_FALSE(initialized);
- }
- static void finishedOK(int run, int finalized) {
- PassTestBase<LoopPass>::finishedOK(run);
- EXPECT_EQ(run, initcount);
- EXPECT_EQ(finalized, fincount);
- }
- using llvm::Pass::doInitialization;
- using llvm::Pass::doFinalization;
- virtual bool doInitialization(Loop* L, LPPassManager &LPM) {
- initialized = true;
- initcount++;
- return false;
- }
- virtual bool runOnLoop(Loop *L, LPPassManager &LPM) {
- EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- run();
- return false;
- }
- virtual bool doFinalization() {
- fincount++;
- finalized = true;
- return false;
- }
- };
- int LPass::initcount=0;
- int LPass::fincount=0;
-
- struct BPass : public PassTestBase<BasicBlockPass> {
- private:
- static int inited;
- static int fin;
- public:
- static void finishedOK(int run, int N) {
- PassTestBase<BasicBlockPass>::finishedOK(run);
- EXPECT_EQ(inited, N);
- EXPECT_EQ(fin, N);
- }
- BPass() {
- inited = 0;
- fin = 0;
- }
- virtual bool doInitialization(Module &M) {
- EXPECT_FALSE(initialized);
- initialized = true;
- return false;
- }
- virtual bool doInitialization(Function &F) {
- inited++;
- return false;
- }
- virtual bool runOnBasicBlock(BasicBlock &BB) {
- EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- run();
- return false;
- }
- virtual bool doFinalization(Function &F) {
- fin++;
- return false;
- }
- virtual bool doFinalization(Module &M) {
- EXPECT_FALSE(finalized);
- finalized = true;
- EXPECT_EQ(0, allocated);
- return false;
- }
- };
- int BPass::inited=0;
- int BPass::fin=0;
-
- struct OnTheFlyTest: public ModulePass {
- public:
- static char ID;
- OnTheFlyTest() : ModulePass(ID) {
- initializeFPassPass(*PassRegistry::getPassRegistry());
- }
- virtual bool runOnModule(Module &M) {
- EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
- for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) {
- Function &F = *I;
- {
- SCOPED_TRACE("Running on the fly function pass");
- getAnalysis<FPass>(F);
- }
- }
- return false;
- }
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<FPass>();
- }
- };
- char OnTheFlyTest::ID=0;
-
- TEST(PassManager, RunOnce) {
- Module M("test-once", getGlobalContext());
- struct ModuleNDNM *mNDNM = new ModuleNDNM();
- struct ModuleDNM *mDNM = new ModuleDNM();
- struct ModuleNDM *mNDM = new ModuleNDM();
- struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
-
- mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
-
- PassManager Passes;
- Passes.add(new DataLayout(&M));
- Passes.add(mNDM2);
- Passes.add(mNDM);
- Passes.add(mNDNM);
- Passes.add(mDNM);
-
- Passes.run(M);
- // each pass must be run exactly once, since nothing invalidates them
- EXPECT_EQ(1, mNDM->run);
- EXPECT_EQ(1, mNDNM->run);
- EXPECT_EQ(1, mDNM->run);
- EXPECT_EQ(1, mNDM2->run);
- }
-
- TEST(PassManager, ReRun) {
- Module M("test-rerun", getGlobalContext());
- struct ModuleNDNM *mNDNM = new ModuleNDNM();
- struct ModuleDNM *mDNM = new ModuleDNM();
- struct ModuleNDM *mNDM = new ModuleNDM();
- struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
-
- mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
-
- PassManager Passes;
- Passes.add(new DataLayout(&M));
- Passes.add(mNDM);
- Passes.add(mNDNM);
- Passes.add(mNDM2);// invalidates mNDM needed by mDNM
- Passes.add(mDNM);
-
- Passes.run(M);
- // Some passes must be rerun because a pass that modified the
- // module/function was run in between
- EXPECT_EQ(2, mNDM->run);
- EXPECT_EQ(1, mNDNM->run);
- EXPECT_EQ(1, mNDM2->run);
- EXPECT_EQ(1, mDNM->run);
- }
-
- Module* makeLLVMModule();
-
- template<typename T>
- void MemoryTestHelper(int run) {
- OwningPtr<Module> M(makeLLVMModule());
- T *P = new T();
- PassManager Passes;
- Passes.add(new DataLayout(M.get()));
- Passes.add(P);
- Passes.run(*M);
- T::finishedOK(run);
- }
-
- template<typename T>
- void MemoryTestHelper(int run, int N) {
- Module *M = makeLLVMModule();
- T *P = new T();
- PassManager Passes;
- Passes.add(new DataLayout(M));
- Passes.add(P);
- Passes.run(*M);
- T::finishedOK(run, N);
- delete M;
- }
-
- TEST(PassManager, Memory) {
- // SCC#1: test1->test2->test3->test1
- // SCC#2: test4
- // SCC#3: indirect call node
- {
- SCOPED_TRACE("Callgraph pass");
- MemoryTestHelper<CGPass>(3);
- }
-
- {
- SCOPED_TRACE("Function pass");
- MemoryTestHelper<FPass>(4);// 4 functions
- }
-
- {
- SCOPED_TRACE("Loop pass");
- MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function
- }
- {
- SCOPED_TRACE("Basic block pass");
- MemoryTestHelper<BPass>(7, 4); //9 basic blocks
- }
-
- }
-
- TEST(PassManager, MemoryOnTheFly) {
- Module *M = makeLLVMModule();
- {
- SCOPED_TRACE("Running OnTheFlyTest");
- struct OnTheFlyTest *O = new OnTheFlyTest();
- PassManager Passes;
- Passes.add(new DataLayout(M));
- Passes.add(O);
- Passes.run(*M);
-
- FPass::finishedOK(4);
- }
- delete M;
- }
-
- Module* makeLLVMModule() {
- // Module Construction
- Module* mod = new Module("test-mem", getGlobalContext());
- mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
- "a0:0:64-s0:64:64-f80:128:128");
- mod->setTargetTriple("x86_64-unknown-linux-gnu");
-
- // Type Definitions
- std::vector<Type*>FuncTy_0_args;
- FunctionType* FuncTy_0 = FunctionType::get(
- /*Result=*/IntegerType::get(getGlobalContext(), 32),
- /*Params=*/FuncTy_0_args,
- /*isVarArg=*/false);
-
- std::vector<Type*>FuncTy_2_args;
- FuncTy_2_args.push_back(IntegerType::get(getGlobalContext(), 1));
- FunctionType* FuncTy_2 = FunctionType::get(
- /*Result=*/Type::getVoidTy(getGlobalContext()),
- /*Params=*/FuncTy_2_args,
- /*isVarArg=*/false);
-
-
- // Function Declarations
-
- Function* func_test1 = Function::Create(
- /*Type=*/FuncTy_0,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"test1", mod);
- func_test1->setCallingConv(CallingConv::C);
- AttributeSet func_test1_PAL;
- func_test1->setAttributes(func_test1_PAL);
-
- Function* func_test2 = Function::Create(
- /*Type=*/FuncTy_0,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"test2", mod);
- func_test2->setCallingConv(CallingConv::C);
- AttributeSet func_test2_PAL;
- func_test2->setAttributes(func_test2_PAL);
-
- Function* func_test3 = Function::Create(
- /*Type=*/FuncTy_0,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"test3", mod);
- func_test3->setCallingConv(CallingConv::C);
- AttributeSet func_test3_PAL;
- func_test3->setAttributes(func_test3_PAL);
-
- Function* func_test4 = Function::Create(
- /*Type=*/FuncTy_2,
- /*Linkage=*/GlobalValue::ExternalLinkage,
- /*Name=*/"test4", mod);
- func_test4->setCallingConv(CallingConv::C);
- AttributeSet func_test4_PAL;
- func_test4->setAttributes(func_test4_PAL);
-
- // Global Variable Declarations
-
-
- // Constant Definitions
-
- // Global Variable Definitions
-
- // Function Definitions
-
- // Function: test1 (func_test1)
- {
-
- BasicBlock* label_entry = BasicBlock::Create(getGlobalContext(), "entry",func_test1,0);
-
- // Block entry (label_entry)
- CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry);
- int32_3->setCallingConv(CallingConv::C);
- int32_3->setTailCall(false);AttributeSet int32_3_PAL;
- int32_3->setAttributes(int32_3_PAL);
-
- ReturnInst::Create(getGlobalContext(), int32_3, label_entry);
-
- }
-
- // Function: test2 (func_test2)
- {
-
- BasicBlock* label_entry_5 = BasicBlock::Create(getGlobalContext(), "entry",func_test2,0);
-
- // Block entry (label_entry_5)
- CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5);
- int32_6->setCallingConv(CallingConv::C);
- int32_6->setTailCall(false);AttributeSet int32_6_PAL;
- int32_6->setAttributes(int32_6_PAL);
-
- ReturnInst::Create(getGlobalContext(), int32_6, label_entry_5);
-
- }
-
- // Function: test3 (func_test3)
- {
+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);
+ }
- BasicBlock* label_entry_8 = BasicBlock::Create(getGlobalContext(), "entry",func_test3,0);
+private:
+ /// \brief Private static data to provide unique ID.
+ static char PassID;
+};
- // Block entry (label_entry_8)
- CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8);
- int32_9->setCallingConv(CallingConv::C);
- int32_9->setTailCall(false);AttributeSet int32_9_PAL;
- int32_9->setAttributes(int32_9_PAL);
+char TestAnalysisPass::PassID;
- ReturnInst::Create(getGlobalContext(), int32_9, label_entry_8);
+struct TestModulePass {
+ TestModulePass(int &RunCount) : RunCount(RunCount) {}
- }
+ bool run(Module *M) {
+ ++RunCount;
+ return true;
+ }
- // Function: test4 (func_test4)
- {
- Function::arg_iterator args = func_test4->arg_begin();
- Value* int1_f = args++;
- int1_f->setName("f");
+ int &RunCount;
+};
- BasicBlock* label_entry_11 = BasicBlock::Create(getGlobalContext(), "entry",func_test4,0);
- BasicBlock* label_bb = BasicBlock::Create(getGlobalContext(), "bb",func_test4,0);
- BasicBlock* label_bb1 = BasicBlock::Create(getGlobalContext(), "bb1",func_test4,0);
- BasicBlock* label_return = BasicBlock::Create(getGlobalContext(), "return",func_test4,0);
+struct TestFunctionPass {
+ TestFunctionPass(AnalysisManager &AM, int &RunCount, int &AnalyzedInstrCount)
+ : AM(AM), RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount) {
+ }
- // Block entry (label_entry_11)
- BranchInst::Create(label_bb, label_entry_11);
+ bool run(Function *F) {
+ ++RunCount;
- // Block bb (label_bb)
- BranchInst::Create(label_bb, label_bb1, int1_f, label_bb);
+ const TestAnalysisPass::Result &AR = AM.getResult<TestAnalysisPass>(F);
+ AnalyzedInstrCount += AR.InstructionCount;
- // Block bb1 (label_bb1)
- BranchInst::Create(label_bb1, label_return, int1_f, label_bb1);
+ return true;
+ }
- // Block return (label_return)
- ReturnInst::Create(getGlobalContext(), label_return);
+ AnalysisManager &AM;
+ int &RunCount;
+ int &AnalyzedInstrCount;
+};
- }
- return mod;
- }
+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) {
+ AnalysisManager AM(M.get());
+ AM.registerAnalysisPass(TestAnalysisPass());
+
+ ModulePassManager MPM(M.get(), &AM);
+ 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();
+ EXPECT_EQ(1, ModulePassRunCount);
+ EXPECT_EQ(3, FunctionPassRunCount);
+ EXPECT_EQ(5, AnalyzedInstrCount);
}
-INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false)
-INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false)
-INITIALIZE_AG_DEPENDENCY(CallGraph)
-INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false)
-INITIALIZE_PASS(FPass, "fp","fp", false, false)
-INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false)
-INITIALIZE_PASS_DEPENDENCY(LoopInfo)
-INITIALIZE_PASS_END(LPass, "lp","lp", false, false)
-INITIALIZE_PASS(BPass, "bp","bp", false, false)
+}
diff --git a/unittests/IR/ValueTest.cpp b/unittests/IR/ValueTest.cpp
index 52efb1a220aa1..ebe23e869401d 100644
--- a/unittests/IR/ValueTest.cpp
+++ b/unittests/IR/ValueTest.cpp
@@ -43,4 +43,44 @@ TEST(ValueTest, UsedInBasicBlock) {
EXPECT_TRUE(F->arg_begin()->isUsedInBasicBlock(F->begin()));
}
+TEST(GlobalTest, CreateAddressSpace) {
+ LLVMContext &Ctx = getGlobalContext();
+ OwningPtr<Module> M(new Module("TestModule", Ctx));
+ Type *Int8Ty = Type::getInt8Ty(Ctx);
+ Type *Int32Ty = Type::getInt32Ty(Ctx);
+
+ GlobalVariable *Dummy0
+ = new GlobalVariable(*M,
+ Int32Ty,
+ true,
+ GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty),
+ "dummy",
+ 0,
+ GlobalVariable::NotThreadLocal,
+ 1);
+
+ // Make sure the address space isn't dropped when returning this.
+ Constant *Dummy1 = M->getOrInsertGlobal("dummy", Int32Ty);
+ EXPECT_EQ(Dummy0, Dummy1);
+ EXPECT_EQ(1u, Dummy1->getType()->getPointerAddressSpace());
+
+
+ // This one requires a bitcast, but the address space must also stay the same.
+ GlobalVariable *DummyCast0
+ = new GlobalVariable(*M,
+ Int32Ty,
+ true,
+ GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty),
+ "dummy_cast",
+ 0,
+ GlobalVariable::NotThreadLocal,
+ 1);
+
+ // Make sure the address space isn't dropped when returning this.
+ Constant *DummyCast1 = M->getOrInsertGlobal("dummy_cast", Int8Ty);
+ EXPECT_EQ(1u, DummyCast1->getType()->getPointerAddressSpace());
+ EXPECT_NE(DummyCast0, DummyCast1) << *DummyCast1;
+}
} // end anonymous namespace
diff --git a/unittests/IR/VerifierTest.cpp b/unittests/IR/VerifierTest.cpp
index 89119368fbd92..31936c392d848 100644
--- a/unittests/IR/VerifierTest.cpp
+++ b/unittests/IR/VerifierTest.cpp
@@ -24,10 +24,11 @@ namespace {
TEST(VerifierTest, Branch_i1) {
LLVMContext &C = getGlobalContext();
+ Module M("M", C);
FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false);
- OwningPtr<Function> F(Function::Create(FTy, GlobalValue::ExternalLinkage));
- BasicBlock *Entry = BasicBlock::Create(C, "entry", F.get());
- BasicBlock *Exit = BasicBlock::Create(C, "exit", F.get());
+ Function *F = cast<Function>(M.getOrInsertFunction("foo", FTy));
+ BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
+ BasicBlock *Exit = BasicBlock::Create(C, "exit", F);
ReturnInst::Create(C, Exit);
// To avoid triggering an assertion in BranchInst::Create, we first create
@@ -60,5 +61,21 @@ TEST(VerifierTest, AliasUnnamedAddr) {
EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error));
EXPECT_TRUE(StringRef(Error).startswith("Alias cannot have unnamed_addr"));
}
+
+TEST(VerifierTest, InvalidRetAttribute) {
+ LLVMContext &C = getGlobalContext();
+ Module M("M", C);
+ FunctionType *FTy = FunctionType::get(Type::getInt32Ty(C), /*isVarArg=*/false);
+ Function *F = cast<Function>(M.getOrInsertFunction("foo", FTy));
+ AttributeSet AS = F->getAttributes();
+ F->setAttributes(AS.addAttribute(C, AttributeSet::ReturnIndex,
+ Attribute::UWTable));
+
+ std::string Error;
+ EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error));
+ EXPECT_TRUE(StringRef(Error).
+ startswith("Attribute 'uwtable' only applies to functions!"));
+}
+
}
}
diff --git a/unittests/IR/WaymarkTest.cpp b/unittests/IR/WaymarkTest.cpp
index cf7d76dffc978..9a9b4a2ad4e7b 100644
--- a/unittests/IR/WaymarkTest.cpp
+++ b/unittests/IR/WaymarkTest.cpp
@@ -9,6 +9,7 @@
// we perform white-box tests
//
+#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"