summaryrefslogtreecommitdiff
path: root/unittests/IR/BasicBlockTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/IR/BasicBlockTest.cpp')
-rw-r--r--unittests/IR/BasicBlockTest.cpp57
1 files changed, 57 insertions, 0 deletions
diff --git a/unittests/IR/BasicBlockTest.cpp b/unittests/IR/BasicBlockTest.cpp
index f1777e35b82c..07ed997f6381 100644
--- a/unittests/IR/BasicBlockTest.cpp
+++ b/unittests/IR/BasicBlockTest.cpp
@@ -33,6 +33,12 @@ TEST(BasicBlockTest, PhiRange) {
std::unique_ptr<BasicBlock> BB2(BasicBlock::Create(Context));
BranchInst::Create(BB.get(), BB2.get());
+ // Make sure this doesn't crash if there are no phis.
+ for (auto &PN : BB->phis()) {
+ (void)PN;
+ EXPECT_TRUE(false) << "empty block should have no phis";
+ }
+
// Make it a cycle.
auto *BI = BranchInst::Create(BB.get(), BB.get());
@@ -63,6 +69,15 @@ TEST(BasicBlockTest, PhiRange) {
CI = BB->phis().begin();
EXPECT_NE(CI, BB->phis().end());
+ // Test that filtering iterators work with basic blocks.
+ auto isPhi = [](Instruction &I) { return isa<PHINode>(&I); };
+ auto Phis = make_filter_range(*BB, isPhi);
+ auto ReversedPhis = reverse(make_filter_range(*BB, isPhi));
+ EXPECT_EQ(std::distance(Phis.begin(), Phis.end()), 3);
+ EXPECT_EQ(&*Phis.begin(), P1);
+ EXPECT_EQ(std::distance(ReversedPhis.begin(), ReversedPhis.end()), 3);
+ EXPECT_EQ(&*ReversedPhis.begin(), P3);
+
// And iterate a const range.
for (const auto &PN : const_cast<const BasicBlock *>(BB.get())->phis()) {
EXPECT_EQ(BB.get(), PN.getIncomingBlock(0));
@@ -71,5 +86,47 @@ TEST(BasicBlockTest, PhiRange) {
}
}
+#define CHECK_ITERATORS(Range1, Range2) \
+ EXPECT_EQ(std::distance(Range1.begin(), Range1.end()), \
+ std::distance(Range2.begin(), Range2.end())); \
+ for (auto Pair : zip(Range1, Range2)) \
+ EXPECT_EQ(&std::get<0>(Pair), std::get<1>(Pair));
+
+TEST(BasicBlockTest, TestInstructionsWithoutDebug) {
+ LLVMContext Ctx;
+
+ Module *M = new Module("MyModule", Ctx);
+ Type *ArgTy1[] = {Type::getInt32PtrTy(Ctx)};
+ FunctionType *FT = FunctionType::get(Type::getVoidTy(Ctx), ArgTy1, false);
+ Argument *V = new Argument(Type::getInt32Ty(Ctx));
+ Function *F = Function::Create(FT, Function::ExternalLinkage, "", M);
+
+ Value *DbgAddr = Intrinsic::getDeclaration(M, Intrinsic::dbg_addr);
+ Value *DbgDeclare =
+ Intrinsic::getDeclaration(M, Intrinsic::dbg_declare);
+ Value *DbgValue = Intrinsic::getDeclaration(M, Intrinsic::dbg_value);
+ Value *DIV = MetadataAsValue::get(Ctx, (Metadata *)nullptr);
+ SmallVector<Value *, 3> Args = {DIV, DIV, DIV};
+
+ BasicBlock *BB1 = BasicBlock::Create(Ctx, "", F);
+ const BasicBlock *BBConst = BB1;
+ IRBuilder<> Builder1(BB1);
+
+ AllocaInst *Var = Builder1.CreateAlloca(Builder1.getInt8Ty());
+ Builder1.CreateCall(DbgValue, Args);
+ Instruction *AddInst = cast<Instruction>(Builder1.CreateAdd(V, V));
+ Instruction *MulInst = cast<Instruction>(Builder1.CreateMul(AddInst, V));
+ Builder1.CreateCall(DbgDeclare, Args);
+ Instruction *SubInst = cast<Instruction>(Builder1.CreateSub(MulInst, V));
+ Builder1.CreateCall(DbgAddr, Args);
+
+ SmallVector<Instruction *, 4> Exp = {Var, AddInst, MulInst, SubInst};
+ CHECK_ITERATORS(BB1->instructionsWithoutDebug(), Exp);
+ CHECK_ITERATORS(BBConst->instructionsWithoutDebug(), Exp);
+
+ delete M;
+ delete V;
+}
+
} // End anonymous namespace.
} // End llvm namespace.