aboutsummaryrefslogtreecommitdiff
path: root/unittests/IR/InstructionsTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/IR/InstructionsTest.cpp')
-rw-r--r--unittests/IR/InstructionsTest.cpp167
1 files changed, 164 insertions, 3 deletions
diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp
index 0dac7c1bcfb1..7c75aaec1753 100644
--- a/unittests/IR/InstructionsTest.cpp
+++ b/unittests/IR/InstructionsTest.cpp
@@ -19,6 +19,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/NoFolder.h"
#include "llvm/IR/Operator.h"
#include "gtest/gtest.h"
#include <memory>
@@ -516,7 +517,8 @@ TEST(InstructionsTest, CloneCall) {
{
AttrBuilder AB;
AB.addAttribute(Attribute::ReadOnly);
- Call->setAttributes(AttributeSet::get(C, AttributeSet::FunctionIndex, AB));
+ Call->setAttributes(
+ AttributeList::get(C, AttributeList::FunctionIndex, AB));
std::unique_ptr<CallInst> Clone(cast<CallInst>(Call->clone()));
EXPECT_TRUE(Clone->onlyReadsMemory());
}
@@ -534,7 +536,7 @@ TEST(InstructionsTest, AlterCallBundles) {
Call->setTailCallKind(CallInst::TailCallKind::TCK_NoTail);
AttrBuilder AB;
AB.addAttribute(Attribute::Cold);
- Call->setAttributes(AttributeSet::get(C, AttributeSet::FunctionIndex, AB));
+ Call->setAttributes(AttributeList::get(C, AttributeList::FunctionIndex, AB));
Call->setDebugLoc(DebugLoc(MDNode::get(C, None)));
OperandBundleDef NewBundle("after", ConstantInt::get(Int32Ty, 7));
@@ -562,7 +564,8 @@ TEST(InstructionsTest, AlterInvokeBundles) {
Callee, NormalDest.get(), UnwindDest.get(), Args, OldBundle, "result"));
AttrBuilder AB;
AB.addAttribute(Attribute::Cold);
- Invoke->setAttributes(AttributeSet::get(C, AttributeSet::FunctionIndex, AB));
+ Invoke->setAttributes(
+ AttributeList::get(C, AttributeList::FunctionIndex, AB));
Invoke->setDebugLoc(DebugLoc(MDNode::get(C, None)));
OperandBundleDef NewBundle("after", ConstantInt::get(Int32Ty, 7));
@@ -579,5 +582,163 @@ TEST(InstructionsTest, AlterInvokeBundles) {
EXPECT_TRUE(Clone->getOperandBundle("after").hasValue());
}
+TEST_F(ModuleWithFunctionTest, DropPoisonGeneratingFlags) {
+ auto *OnlyBB = BasicBlock::Create(Ctx, "bb", F);
+ auto *Arg0 = &*F->arg_begin();
+
+ IRBuilder<NoFolder> B(Ctx);
+ B.SetInsertPoint(OnlyBB);
+
+ {
+ auto *UI =
+ cast<Instruction>(B.CreateUDiv(Arg0, Arg0, "", /*isExact*/ true));
+ ASSERT_TRUE(UI->isExact());
+ UI->dropPoisonGeneratingFlags();
+ ASSERT_FALSE(UI->isExact());
+ }
+
+ {
+ auto *ShrI =
+ cast<Instruction>(B.CreateLShr(Arg0, Arg0, "", /*isExact*/ true));
+ ASSERT_TRUE(ShrI->isExact());
+ ShrI->dropPoisonGeneratingFlags();
+ ASSERT_FALSE(ShrI->isExact());
+ }
+
+ {
+ auto *AI = cast<Instruction>(
+ B.CreateAdd(Arg0, Arg0, "", /*HasNUW*/ true, /*HasNSW*/ false));
+ ASSERT_TRUE(AI->hasNoUnsignedWrap());
+ AI->dropPoisonGeneratingFlags();
+ ASSERT_FALSE(AI->hasNoUnsignedWrap());
+ ASSERT_FALSE(AI->hasNoSignedWrap());
+ }
+
+ {
+ auto *SI = cast<Instruction>(
+ B.CreateAdd(Arg0, Arg0, "", /*HasNUW*/ false, /*HasNSW*/ true));
+ ASSERT_TRUE(SI->hasNoSignedWrap());
+ SI->dropPoisonGeneratingFlags();
+ ASSERT_FALSE(SI->hasNoUnsignedWrap());
+ ASSERT_FALSE(SI->hasNoSignedWrap());
+ }
+
+ {
+ auto *ShlI = cast<Instruction>(
+ B.CreateShl(Arg0, Arg0, "", /*HasNUW*/ true, /*HasNSW*/ true));
+ ASSERT_TRUE(ShlI->hasNoSignedWrap());
+ ASSERT_TRUE(ShlI->hasNoUnsignedWrap());
+ ShlI->dropPoisonGeneratingFlags();
+ ASSERT_FALSE(ShlI->hasNoUnsignedWrap());
+ ASSERT_FALSE(ShlI->hasNoSignedWrap());
+ }
+
+ {
+ Value *GEPBase = Constant::getNullValue(B.getInt8PtrTy());
+ auto *GI = cast<GetElementPtrInst>(B.CreateInBoundsGEP(GEPBase, {Arg0}));
+ ASSERT_TRUE(GI->isInBounds());
+ GI->dropPoisonGeneratingFlags();
+ ASSERT_FALSE(GI->isInBounds());
+ }
+}
+
+TEST(InstructionsTest, GEPIndices) {
+ LLVMContext Context;
+ IRBuilder<NoFolder> Builder(Context);
+ Type *ElementTy = Builder.getInt8Ty();
+ Type *ArrTy = ArrayType::get(ArrayType::get(ElementTy, 64), 64);
+ Value *Indices[] = {
+ Builder.getInt32(0),
+ Builder.getInt32(13),
+ Builder.getInt32(42) };
+
+ Value *V = Builder.CreateGEP(ArrTy, UndefValue::get(PointerType::getUnqual(ArrTy)),
+ Indices);
+ ASSERT_TRUE(isa<GetElementPtrInst>(V));
+
+ auto *GEPI = cast<GetElementPtrInst>(V);
+ ASSERT_NE(GEPI->idx_begin(), GEPI->idx_end());
+ ASSERT_EQ(GEPI->idx_end(), std::next(GEPI->idx_begin(), 3));
+ EXPECT_EQ(Indices[0], GEPI->idx_begin()[0]);
+ EXPECT_EQ(Indices[1], GEPI->idx_begin()[1]);
+ EXPECT_EQ(Indices[2], GEPI->idx_begin()[2]);
+ EXPECT_EQ(GEPI->idx_begin(), GEPI->indices().begin());
+ EXPECT_EQ(GEPI->idx_end(), GEPI->indices().end());
+
+ const auto *CGEPI = GEPI;
+ ASSERT_NE(CGEPI->idx_begin(), CGEPI->idx_end());
+ ASSERT_EQ(CGEPI->idx_end(), std::next(CGEPI->idx_begin(), 3));
+ EXPECT_EQ(Indices[0], CGEPI->idx_begin()[0]);
+ EXPECT_EQ(Indices[1], CGEPI->idx_begin()[1]);
+ EXPECT_EQ(Indices[2], CGEPI->idx_begin()[2]);
+ EXPECT_EQ(CGEPI->idx_begin(), CGEPI->indices().begin());
+ EXPECT_EQ(CGEPI->idx_end(), CGEPI->indices().end());
+
+ delete GEPI;
+}
+
+TEST(InstructionsTest, SwitchInst) {
+ LLVMContext C;
+
+ std::unique_ptr<BasicBlock> BB1, BB2, BB3;
+ BB1.reset(BasicBlock::Create(C));
+ BB2.reset(BasicBlock::Create(C));
+ BB3.reset(BasicBlock::Create(C));
+
+ // We create block 0 after the others so that it gets destroyed first and
+ // clears the uses of the other basic blocks.
+ std::unique_ptr<BasicBlock> BB0(BasicBlock::Create(C));
+
+ auto *Int32Ty = Type::getInt32Ty(C);
+
+ SwitchInst *SI =
+ SwitchInst::Create(UndefValue::get(Int32Ty), BB0.get(), 3, BB0.get());
+ SI->addCase(ConstantInt::get(Int32Ty, 1), BB1.get());
+ SI->addCase(ConstantInt::get(Int32Ty, 2), BB2.get());
+ SI->addCase(ConstantInt::get(Int32Ty, 3), BB3.get());
+
+ auto CI = SI->case_begin();
+ ASSERT_NE(CI, SI->case_end());
+ EXPECT_EQ(1, CI->getCaseValue()->getSExtValue());
+ EXPECT_EQ(BB1.get(), CI->getCaseSuccessor());
+ EXPECT_EQ(2, (CI + 1)->getCaseValue()->getSExtValue());
+ EXPECT_EQ(BB2.get(), (CI + 1)->getCaseSuccessor());
+ EXPECT_EQ(3, (CI + 2)->getCaseValue()->getSExtValue());
+ EXPECT_EQ(BB3.get(), (CI + 2)->getCaseSuccessor());
+ EXPECT_EQ(CI + 1, std::next(CI));
+ EXPECT_EQ(CI + 2, std::next(CI, 2));
+ EXPECT_EQ(CI + 3, std::next(CI, 3));
+ EXPECT_EQ(SI->case_end(), CI + 3);
+ EXPECT_EQ(0, CI - CI);
+ EXPECT_EQ(1, (CI + 1) - CI);
+ EXPECT_EQ(2, (CI + 2) - CI);
+ EXPECT_EQ(3, SI->case_end() - CI);
+ EXPECT_EQ(3, std::distance(CI, SI->case_end()));
+
+ auto CCI = const_cast<const SwitchInst *>(SI)->case_begin();
+ SwitchInst::ConstCaseIt CCE = SI->case_end();
+ ASSERT_NE(CCI, SI->case_end());
+ EXPECT_EQ(1, CCI->getCaseValue()->getSExtValue());
+ EXPECT_EQ(BB1.get(), CCI->getCaseSuccessor());
+ EXPECT_EQ(2, (CCI + 1)->getCaseValue()->getSExtValue());
+ EXPECT_EQ(BB2.get(), (CCI + 1)->getCaseSuccessor());
+ EXPECT_EQ(3, (CCI + 2)->getCaseValue()->getSExtValue());
+ EXPECT_EQ(BB3.get(), (CCI + 2)->getCaseSuccessor());
+ EXPECT_EQ(CCI + 1, std::next(CCI));
+ EXPECT_EQ(CCI + 2, std::next(CCI, 2));
+ EXPECT_EQ(CCI + 3, std::next(CCI, 3));
+ EXPECT_EQ(CCE, CCI + 3);
+ EXPECT_EQ(0, CCI - CCI);
+ EXPECT_EQ(1, (CCI + 1) - CCI);
+ EXPECT_EQ(2, (CCI + 2) - CCI);
+ EXPECT_EQ(3, CCE - CCI);
+ EXPECT_EQ(3, std::distance(CCI, CCE));
+
+ // Make sure that the const iterator is compatible with a const auto ref.
+ const auto &Handle = *CCI;
+ EXPECT_EQ(1, Handle.getCaseValue()->getSExtValue());
+ EXPECT_EQ(BB1.get(), Handle.getCaseSuccessor());
+}
+
} // end anonymous namespace
} // end namespace llvm