aboutsummaryrefslogtreecommitdiffstats
path: root/unittests/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/Transforms')
-rw-r--r--unittests/Transforms/DebugIR/CMakeLists.txt2
-rw-r--r--unittests/Transforms/DebugIR/DebugIR.cpp22
-rw-r--r--unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp102
-rw-r--r--unittests/Transforms/Utils/CMakeLists.txt3
-rw-r--r--unittests/Transforms/Utils/Cloning.cpp235
-rw-r--r--unittests/Transforms/Utils/IntegerDivision.cpp122
-rw-r--r--unittests/Transforms/Utils/SpecialCaseList.cpp23
7 files changed, 486 insertions, 23 deletions
diff --git a/unittests/Transforms/DebugIR/CMakeLists.txt b/unittests/Transforms/DebugIR/CMakeLists.txt
index 4b47193..88734d2 100644
--- a/unittests/Transforms/DebugIR/CMakeLists.txt
+++ b/unittests/Transforms/DebugIR/CMakeLists.txt
@@ -1,5 +1,7 @@
set(LLVM_LINK_COMPONENTS
+ Core
Instrumentation
+ Support
)
add_llvm_unittest(DebugIRTests
diff --git a/unittests/Transforms/DebugIR/DebugIR.cpp b/unittests/Transforms/DebugIR/DebugIR.cpp
index 7d213fd..9b89c15 100644
--- a/unittests/Transforms/DebugIR/DebugIR.cpp
+++ b/unittests/Transforms/DebugIR/DebugIR.cpp
@@ -13,17 +13,16 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/Triple.h"
+#include "../lib/Transforms/Instrumentation/DebugIR.h"
#include "llvm/Config/config.h"
-#include "llvm/DebugInfo.h"
-#include "llvm/DIBuilder.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Module.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/Path.h"
#include "llvm/Transforms/Instrumentation.h"
-#include "../lib/Transforms/Instrumentation/DebugIR.h"
-
// These tests do not depend on MCJIT, but we use the TrivialModuleBuilder
// helper class to construct some trivial Modules.
#include "../unittests/ExecutionEngine/MCJIT/MCJITTestBase.h"
@@ -56,9 +55,10 @@ void insertCUDescriptor(Module *M, StringRef File, StringRef Dir,
/// Attempts to remove file at Path and returns true if it existed, or false if
/// it did not.
bool removeIfExists(StringRef Path) {
- bool existed = false;
- sys::fs::remove(Path, existed);
- return existed;
+ // This is an approximation, on error we don't know in general if the file
+ // existed or not.
+ llvm::error_code EC = sys::fs::remove(Path, false);
+ return EC != llvm::errc::no_such_file_or_directory;
}
char * current_dir() {
@@ -90,8 +90,8 @@ protected:
LLVMContext Context;
char *cwd;
- OwningPtr<Module> M;
- OwningPtr<DebugIR> D;
+ std::unique_ptr<Module> M;
+ std::unique_ptr<DebugIR> D;
};
// Test empty named Module that is not supposed to be output to disk.
@@ -278,7 +278,7 @@ TEST_F(TestDebugIR, ExistingMetadataRetained) {
// verify DebugIR did not generate a file
ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path;
- DICompileUnit CU(*Finder.compile_unit_begin());
+ DICompileUnit CU(*Finder.compile_units().begin());
// Verify original CU information is retained
ASSERT_EQ(Filename, CU.getFilename());
diff --git a/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp b/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp
new file mode 100644
index 0000000..0d3a239
--- /dev/null
+++ b/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp
@@ -0,0 +1,102 @@
+//===- ASanStackFrameLayoutTest.cpp - Tests for ComputeASanStackFrameLayout===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/Transforms/Utils/ASanStackFrameLayout.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "gtest/gtest.h"
+#include <sstream>
+
+using namespace llvm;
+
+static std::string
+ShadowBytesToString(ArrayRef<uint8_t> ShadowBytes) {
+ std::ostringstream os;
+ for (size_t i = 0, n = ShadowBytes.size(); i < n; i++) {
+ switch (ShadowBytes[i]) {
+ case kAsanStackLeftRedzoneMagic: os << "L"; break;
+ case kAsanStackRightRedzoneMagic: os << "R"; break;
+ case kAsanStackMidRedzoneMagic: os << "M"; break;
+ default: os << (unsigned)ShadowBytes[i];
+ }
+ }
+ return os.str();
+}
+
+static void TestLayout(SmallVector<ASanStackVariableDescription, 10> Vars,
+ size_t Granularity, size_t MinHeaderSize,
+ const std::string &ExpectedDescr,
+ const std::string &ExpectedShadow) {
+ ASanStackFrameLayout L;
+ ComputeASanStackFrameLayout(Vars, Granularity, MinHeaderSize, &L);
+ EXPECT_EQ(ExpectedDescr, L.DescriptionString);
+ EXPECT_EQ(ExpectedShadow, ShadowBytesToString(L.ShadowBytes));
+}
+
+TEST(ASanStackFrameLayout, Test) {
+#define VEC1(a) SmallVector<ASanStackVariableDescription, 10>(1, a)
+#define VEC(a) \
+ SmallVector<ASanStackVariableDescription, 10>(a, a + sizeof(a) / sizeof(a[0]))
+
+#define VAR(name, size, alignment) \
+ ASanStackVariableDescription name##size##_##alignment = { \
+ #name #size "_" #alignment, \
+ size, \
+ alignment, \
+ 0, \
+ 0 \
+ }
+
+ VAR(a, 1, 1);
+ VAR(p, 1, 32);
+ VAR(p, 1, 256);
+ VAR(a, 2, 1);
+ VAR(a, 3, 1);
+ VAR(a, 4, 1);
+ VAR(a, 7, 1);
+ VAR(a, 8, 1);
+ VAR(a, 9, 1);
+ VAR(a, 16, 1);
+ VAR(a, 41, 1);
+ VAR(a, 105, 1);
+
+ TestLayout(VEC1(a1_1), 8, 16, "1 16 1 4 a1_1", "LL1R");
+ TestLayout(VEC1(a1_1), 64, 64, "1 64 1 4 a1_1", "L1");
+ TestLayout(VEC1(p1_32), 8, 32, "1 32 1 5 p1_32", "LLLL1RRR");
+ TestLayout(VEC1(p1_32), 8, 64, "1 64 1 5 p1_32", "LLLLLLLL1RRRRRRR");
+
+ TestLayout(VEC1(a1_1), 8, 32, "1 32 1 4 a1_1", "LLLL1RRR");
+ TestLayout(VEC1(a2_1), 8, 32, "1 32 2 4 a2_1", "LLLL2RRR");
+ TestLayout(VEC1(a3_1), 8, 32, "1 32 3 4 a3_1", "LLLL3RRR");
+ TestLayout(VEC1(a4_1), 8, 32, "1 32 4 4 a4_1", "LLLL4RRR");
+ TestLayout(VEC1(a7_1), 8, 32, "1 32 7 4 a7_1", "LLLL7RRR");
+ TestLayout(VEC1(a8_1), 8, 32, "1 32 8 4 a8_1", "LLLL0RRR");
+ TestLayout(VEC1(a9_1), 8, 32, "1 32 9 4 a9_1", "LLLL01RR");
+ TestLayout(VEC1(a16_1), 8, 32, "1 32 16 5 a16_1", "LLLL00RR");
+ TestLayout(VEC1(p1_256), 8, 32, "1 256 1 6 p1_256",
+ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR");
+ TestLayout(VEC1(a41_1), 8, 32, "1 32 41 5 a41_1", "LLLL000001RRRRRR");
+ TestLayout(VEC1(a105_1), 8, 32, "1 32 105 6 a105_1",
+ "LLLL00000000000001RRRRRR");
+
+ {
+ ASanStackVariableDescription t[] = {a1_1, p1_256};
+ TestLayout(VEC(t), 8, 32,
+ "2 256 1 6 p1_256 272 1 4 a1_1",
+ "LLLLLLLL" "LLLLLLLL" "LLLLLLLL" "LLLLLLLL" "1M1R");
+ }
+
+ {
+ ASanStackVariableDescription t[] = {a1_1, a16_1, a41_1};
+ TestLayout(VEC(t), 8, 32,
+ "3 32 1 4 a1_1 48 16 5 a16_1 80 41 5 a41_1",
+ "LLLL" "1M00" "MM00" "0001" "RRRR");
+ }
+#undef VEC1
+#undef VEC
+#undef VAR
+}
diff --git a/unittests/Transforms/Utils/CMakeLists.txt b/unittests/Transforms/Utils/CMakeLists.txt
index 0656390..60447bb 100644
--- a/unittests/Transforms/Utils/CMakeLists.txt
+++ b/unittests/Transforms/Utils/CMakeLists.txt
@@ -1,8 +1,11 @@
set(LLVM_LINK_COMPONENTS
+ Core
+ Support
TransformUtils
)
add_llvm_unittest(UtilsTests
+ ASanStackFrameLayoutTest.cpp
Cloning.cpp
IntegerDivision.cpp
Local.cpp
diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp
index e19ae5b..fb27dc1 100644
--- a/unittests/Transforms/Utils/Cloning.cpp
+++ b/unittests/Transforms/Utils/Cloning.cpp
@@ -7,15 +7,22 @@
//
//===----------------------------------------------------------------------===//
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/Constant.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Module.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/Transforms/Utils/Cloning.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -173,4 +180,230 @@ TEST_F(CloneInstruction, Attributes) {
delete F2;
}
+TEST_F(CloneInstruction, CallingConvention) {
+ Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
+ FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
+
+ Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
+ F1->setCallingConv(CallingConv::Cold);
+ BasicBlock *BB = BasicBlock::Create(context, "", F1);
+ IRBuilder<> Builder(BB);
+ Builder.CreateRetVoid();
+
+ Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
+
+ SmallVector<ReturnInst*, 4> Returns;
+ ValueToValueMapTy VMap;
+ VMap[F1->arg_begin()] = F2->arg_begin();
+
+ CloneFunctionInto(F2, F1, VMap, false, Returns);
+ EXPECT_EQ(CallingConv::Cold, F2->getCallingConv());
+
+ delete F1;
+ delete F2;
+}
+
+class CloneFunc : public ::testing::Test {
+protected:
+ virtual void SetUp() {
+ SetupModule();
+ CreateOldFunc();
+ CreateNewFunc();
+ SetupFinder();
+ }
+
+ virtual void TearDown() {
+ delete Finder;
+ }
+
+ void SetupModule() {
+ M = new Module("", C);
+ }
+
+ void CreateOldFunc() {
+ FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false);
+ OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M);
+ CreateOldFunctionBodyAndDI();
+ }
+
+ void CreateOldFunctionBodyAndDI() {
+ DIBuilder DBuilder(*M);
+ IRBuilder<> IBuilder(C);
+
+ // Function DI
+ DIFile File = DBuilder.createFile("filename.c", "/file/dir/");
+ DIArray ParamTypes = DBuilder.getOrCreateArray(ArrayRef<Value*>());
+ DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes);
+ DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99,
+ "filename.c", "/file/dir", "CloneFunc", false, "", 0);
+
+ DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4,
+ FuncType, true, true, 3, 0, false, OldFunc);
+
+ // Function body
+ BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc);
+ IBuilder.SetInsertPoint(Entry);
+ DebugLoc Loc = DebugLoc::get(3, 2, Subprogram);
+ IBuilder.SetCurrentDebugLocation(Loc);
+ AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C));
+ IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram));
+ Value* AllocaContent = IBuilder.getInt32(1);
+ Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca);
+ IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram));
+ Instruction* Terminator = IBuilder.CreateRetVoid();
+
+ // Create a local variable around the alloca
+ DIType IntType = DBuilder.createBasicType("int", 32, 0,
+ dwarf::DW_ATE_signed);
+ DIVariable Variable = DBuilder.createLocalVariable(
+ dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true);
+ DBuilder.insertDeclare(Alloca, Variable, Store);
+ DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, Terminator);
+ // Finalize the debug info
+ DBuilder.finalize();
+
+
+ // Create another, empty, compile unit
+ DIBuilder DBuilder2(*M);
+ DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
+ "extra.c", "/file/dir", "CloneFunc", false, "", 0);
+ DBuilder2.finalize();
+ }
+
+ void CreateNewFunc() {
+ ValueToValueMapTy VMap;
+ NewFunc = CloneFunction(OldFunc, VMap, true, NULL);
+ M->getFunctionList().push_back(NewFunc);
+ }
+
+ void SetupFinder() {
+ Finder = new DebugInfoFinder();
+ Finder->processModule(*M);
+ }
+
+ LLVMContext C;
+ Function* OldFunc;
+ Function* NewFunc;
+ Module* M;
+ DebugInfoFinder* Finder;
+};
+
+// Test that a new, distinct function was created.
+TEST_F(CloneFunc, NewFunctionCreated) {
+ EXPECT_NE(OldFunc, NewFunc);
+}
+
+// Test that a new subprogram entry was added and is pointing to the new
+// function, while the original subprogram still points to the old one.
+TEST_F(CloneFunc, Subprogram) {
+ unsigned SubprogramCount = Finder->subprogram_count();
+ EXPECT_EQ(2U, SubprogramCount);
+
+ auto Iter = Finder->subprograms().begin();
+ DISubprogram Sub1(*Iter);
+ EXPECT_TRUE(Sub1.Verify());
+ Iter++;
+ DISubprogram Sub2(*Iter);
+ EXPECT_TRUE(Sub2.Verify());
+
+ EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc)
+ || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc));
+}
+
+// Test that the new subprogram entry was not added to the CU which doesn't
+// contain the old subprogram entry.
+TEST_F(CloneFunc, SubprogramInRightCU) {
+ EXPECT_EQ(2U, Finder->compile_unit_count());
+
+ auto Iter = Finder->compile_units().begin();
+ DICompileUnit CU1(*Iter);
+ EXPECT_TRUE(CU1.Verify());
+ Iter++;
+ DICompileUnit CU2(*Iter);
+ EXPECT_TRUE(CU2.Verify());
+ EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0
+ || CU2.getSubprograms().getNumElements() == 0);
+}
+
+// Test that instructions in the old function still belong to it in the
+// metadata, while instruction in the new function belong to the new one.
+TEST_F(CloneFunc, InstructionOwnership) {
+ inst_iterator OldIter = inst_begin(OldFunc);
+ inst_iterator OldEnd = inst_end(OldFunc);
+ inst_iterator NewIter = inst_begin(NewFunc);
+ inst_iterator NewEnd = inst_end(NewFunc);
+ while (OldIter != OldEnd && NewIter != NewEnd) {
+ Instruction& OldI = *OldIter;
+ Instruction& NewI = *NewIter;
+ EXPECT_NE(&OldI, &NewI);
+
+ EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
+ if (OldI.hasMetadata()) {
+ const DebugLoc& OldDL = OldI.getDebugLoc();
+ const DebugLoc& NewDL = NewI.getDebugLoc();
+
+ // Verify that the debug location data is the same
+ EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
+ EXPECT_EQ(OldDL.getCol(), NewDL.getCol());
+
+ // But that they belong to different functions
+ DISubprogram OldSubprogram(OldDL.getScope(C));
+ DISubprogram NewSubprogram(NewDL.getScope(C));
+ EXPECT_TRUE(OldSubprogram.Verify());
+ EXPECT_TRUE(NewSubprogram.Verify());
+ EXPECT_EQ(OldFunc, OldSubprogram.getFunction());
+ EXPECT_EQ(NewFunc, NewSubprogram.getFunction());
+ }
+
+ ++OldIter;
+ ++NewIter;
+ }
+ EXPECT_EQ(OldEnd, OldIter);
+ EXPECT_EQ(NewEnd, NewIter);
+}
+
+// Test that the arguments for debug intrinsics in the new function were
+// properly cloned
+TEST_F(CloneFunc, DebugIntrinsics) {
+ inst_iterator OldIter = inst_begin(OldFunc);
+ inst_iterator OldEnd = inst_end(OldFunc);
+ inst_iterator NewIter = inst_begin(NewFunc);
+ inst_iterator NewEnd = inst_end(NewFunc);
+ while (OldIter != OldEnd && NewIter != NewEnd) {
+ Instruction& OldI = *OldIter;
+ Instruction& NewI = *NewIter;
+ if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
+ DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
+ EXPECT_TRUE(NewIntrin);
+
+ // Old address must belong to the old function
+ EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
+ getParent()->getParent());
+ // New address must belong to the new function
+ EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
+ getParent()->getParent());
+
+ // Old variable must belong to the old function
+ EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
+ .getContext()).getFunction());
+ // New variable must belong to the New function
+ EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
+ .getContext()).getFunction());
+ } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
+ DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
+ EXPECT_TRUE(NewIntrin);
+
+ // Old variable must belong to the old function
+ EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
+ .getContext()).getFunction());
+ // New variable must belong to the New function
+ EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
+ .getContext()).getFunction());
+ }
+
+ ++OldIter;
+ ++NewIter;
+ }
+}
+
}
diff --git a/unittests/Transforms/Utils/IntegerDivision.cpp b/unittests/Transforms/Utils/IntegerDivision.cpp
index 44c2328..f7318a2 100644
--- a/unittests/Transforms/Utils/IntegerDivision.cpp
+++ b/unittests/Transforms/Utils/IntegerDivision.cpp
@@ -19,6 +19,7 @@ using namespace llvm;
namespace {
+
TEST(IntegerDivision, SDiv) {
LLVMContext &C(getGlobalContext());
Module M("test division", C);
@@ -139,4 +140,125 @@ TEST(IntegerDivision, URem) {
EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
}
+
+TEST(IntegerDivision, SDiv64) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test division", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = AI++;
+ Value *B = AI++;
+
+ Value *Div = Builder.CreateSDiv(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
+
+ Value *Ret = Builder.CreateRet(Div);
+
+ expandDivision(cast<BinaryOperator>(Div));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
+
+ Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
+}
+
+TEST(IntegerDivision, UDiv64) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test division", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = AI++;
+ Value *B = AI++;
+
+ Value *Div = Builder.CreateUDiv(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
+
+ Value *Ret = Builder.CreateRet(Div);
+
+ expandDivision(cast<BinaryOperator>(Div));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
+
+ Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
+}
+
+TEST(IntegerDivision, SRem64) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test remainder", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = AI++;
+ Value *B = AI++;
+
+ Value *Rem = Builder.CreateSRem(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
+
+ Value *Ret = Builder.CreateRet(Rem);
+
+ expandRemainder(cast<BinaryOperator>(Rem));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
+
+ Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
+}
+
+TEST(IntegerDivision, URem64) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test remainder", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = AI++;
+ Value *B = AI++;
+
+ Value *Rem = Builder.CreateURem(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
+
+ Value *Ret = Builder.CreateRet(Rem);
+
+ expandRemainder(cast<BinaryOperator>(Rem));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
+
+ Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
+}
+
}
diff --git a/unittests/Transforms/Utils/SpecialCaseList.cpp b/unittests/Transforms/Utils/SpecialCaseList.cpp
index 07ac908..748834f 100644
--- a/unittests/Transforms/Utils/SpecialCaseList.cpp
+++ b/unittests/Transforms/Utils/SpecialCaseList.cpp
@@ -40,7 +40,7 @@ protected:
}
SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) {
- OwningPtr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List));
+ std::unique_ptr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List));
return SpecialCaseList::create(MB.get(), Error);
}
@@ -60,9 +60,10 @@ TEST_F(SpecialCaseListTest, ModuleIsIn) {
Function *F = makeFunction("foo", M);
GlobalVariable *GV = makeGlobal("bar", "t", M);
- OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("# This is a comment.\n"
- "\n"
- "src:hello\n"));
+ std::unique_ptr<SpecialCaseList> SCL(
+ makeSpecialCaseList("# This is a comment.\n"
+ "\n"
+ "src:hello\n"));
EXPECT_TRUE(SCL->isIn(M));
EXPECT_TRUE(SCL->isIn(*F));
EXPECT_TRUE(SCL->isIn(*GV));
@@ -83,7 +84,7 @@ TEST_F(SpecialCaseListTest, FunctionIsIn) {
Function *Foo = makeFunction("foo", M);
Function *Bar = makeFunction("bar", M);
- OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n"));
+ std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n"));
EXPECT_TRUE(SCL->isIn(*Foo));
EXPECT_FALSE(SCL->isIn(*Bar));
@@ -107,7 +108,7 @@ TEST_F(SpecialCaseListTest, GlobalIsIn) {
GlobalVariable *Foo = makeGlobal("foo", "t1", M);
GlobalVariable *Bar = makeGlobal("bar", "t2", M);
- OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("global:foo\n"));
+ std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("global:foo\n"));
EXPECT_TRUE(SCL->isIn(*Foo));
EXPECT_FALSE(SCL->isIn(*Bar));
EXPECT_FALSE(SCL->isIn(*Foo, "init"));
@@ -157,7 +158,7 @@ TEST_F(SpecialCaseListTest, AliasIsIn) {
GlobalAlias *FooAlias = makeAlias("fooalias", Foo);
GlobalAlias *BarAlias = makeAlias("baralias", Bar);
- OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n"));
+ std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n"));
EXPECT_FALSE(SCL->isIn(*FooAlias));
EXPECT_FALSE(SCL->isIn(*BarAlias));
@@ -193,9 +194,9 @@ TEST_F(SpecialCaseListTest, Substring) {
GlobalAlias *GA1 = makeAlias("buffoonery", F);
GlobalAlias *GA2 = makeAlias("foobar", GV);
- OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("src:hello\n"
- "fun:foo\n"
- "global:bar\n"));
+ std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("src:hello\n"
+ "fun:foo\n"
+ "global:bar\n"));
EXPECT_FALSE(SCL->isIn(M));
EXPECT_FALSE(SCL->isIn(*F));
EXPECT_FALSE(SCL->isIn(*GV));
@@ -224,7 +225,7 @@ TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) {
}
TEST_F(SpecialCaseListTest, EmptySpecialCaseList) {
- OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList(""));
+ std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList(""));
Module M("foo", Ctx);
EXPECT_FALSE(SCL->isIn(M));
}