Imported Upstream version 5.18.0.167

Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-10-20 08:25:10 +00:00
parent e19d552987
commit b084638f15
28489 changed files with 184 additions and 3866856 deletions

View File

@ -1,3 +0,0 @@
add_subdirectory(IPO)
add_subdirectory(Scalar)
add_subdirectory(Utils)

View File

@ -1,10 +0,0 @@
set(LLVM_LINK_COMPONENTS
Core
Support
IPO
)
add_llvm_unittest(IPOTests
LowerTypeTests.cpp
WholeProgramDevirt.cpp
)

View File

@ -1,156 +0,0 @@
//===- LowerTypeTests.cpp - Unit tests for type test lowering -------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/LowerTypeTests.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace lowertypetests;
TEST(LowerTypeTests, BitSetBuilder) {
struct {
std::vector<uint64_t> Offsets;
std::set<uint64_t> Bits;
uint64_t ByteOffset;
uint64_t BitSize;
unsigned AlignLog2;
bool IsSingleOffset;
bool IsAllOnes;
} BSBTests[] = {
{{}, std::set<uint64_t>{}, 0, 1, 0, false, false},
{{0}, {0}, 0, 1, 0, true, true},
{{4}, {0}, 4, 1, 0, true, true},
{{37}, {0}, 37, 1, 0, true, true},
{{0, 1}, {0, 1}, 0, 2, 0, false, true},
{{0, 4}, {0, 1}, 0, 2, 2, false, true},
{{0, uint64_t(1) << 33}, {0, 1}, 0, 2, 33, false, true},
{{3, 7}, {0, 1}, 3, 2, 2, false, true},
{{0, 1, 7}, {0, 1, 7}, 0, 8, 0, false, false},
{{0, 2, 14}, {0, 1, 7}, 0, 8, 1, false, false},
{{0, 1, 8}, {0, 1, 8}, 0, 9, 0, false, false},
{{0, 2, 16}, {0, 1, 8}, 0, 9, 1, false, false},
{{0, 1, 2, 3, 4, 5, 6, 7},
{0, 1, 2, 3, 4, 5, 6, 7},
0,
8,
0,
false,
true},
{{0, 1, 2, 3, 4, 5, 6, 7, 8},
{0, 1, 2, 3, 4, 5, 6, 7, 8},
0,
9,
0,
false,
true},
};
for (auto &&T : BSBTests) {
BitSetBuilder BSB;
for (auto Offset : T.Offsets)
BSB.addOffset(Offset);
BitSetInfo BSI = BSB.build();
EXPECT_EQ(T.Bits, BSI.Bits);
EXPECT_EQ(T.ByteOffset, BSI.ByteOffset);
EXPECT_EQ(T.BitSize, BSI.BitSize);
EXPECT_EQ(T.AlignLog2, BSI.AlignLog2);
EXPECT_EQ(T.IsSingleOffset, BSI.isSingleOffset());
EXPECT_EQ(T.IsAllOnes, BSI.isAllOnes());
for (auto Offset : T.Offsets)
EXPECT_TRUE(BSI.containsGlobalOffset(Offset));
auto I = T.Offsets.begin();
for (uint64_t NonOffset = 0; NonOffset != 256; ++NonOffset) {
if (I != T.Offsets.end() && *I == NonOffset) {
++I;
continue;
}
EXPECT_FALSE(BSI.containsGlobalOffset(NonOffset));
}
}
}
TEST(LowerTypeTests, GlobalLayoutBuilder) {
struct {
uint64_t NumObjects;
std::vector<std::set<uint64_t>> Fragments;
std::vector<uint64_t> WantLayout;
} GLBTests[] = {
{0, {}, {}},
{4, {{0, 1}, {2, 3}}, {0, 1, 2, 3}},
{3, {{0, 1}, {1, 2}}, {0, 1, 2}},
{4, {{0, 1}, {1, 2}, {2, 3}}, {0, 1, 2, 3}},
{4, {{0, 1}, {2, 3}, {1, 2}}, {0, 1, 2, 3}},
{6, {{2, 5}, {0, 1, 2, 3, 4, 5}}, {0, 1, 2, 5, 3, 4}},
};
for (auto &&T : GLBTests) {
GlobalLayoutBuilder GLB(T.NumObjects);
for (auto &&F : T.Fragments)
GLB.addFragment(F);
std::vector<uint64_t> ComputedLayout;
for (auto &&F : GLB.Fragments)
ComputedLayout.insert(ComputedLayout.end(), F.begin(), F.end());
EXPECT_EQ(T.WantLayout, ComputedLayout);
}
}
TEST(LowerTypeTests, ByteArrayBuilder) {
struct BABAlloc {
std::set<uint64_t> Bits;
uint64_t BitSize;
uint64_t WantByteOffset;
uint8_t WantMask;
};
struct {
std::vector<BABAlloc> Allocs;
std::vector<uint8_t> WantBytes;
} BABTests[] = {
{{{{0}, 1, 0, 1}, {{0}, 1, 0, 2}}, {3}},
{{{{0}, 16, 0, 1},
{{1}, 15, 0, 2},
{{2}, 14, 0, 4},
{{3}, 13, 0, 8},
{{4}, 12, 0, 0x10},
{{5}, 11, 0, 0x20},
{{6}, 10, 0, 0x40},
{{7}, 9, 0, 0x80},
{{0}, 7, 9, 0x80},
{{0}, 6, 10, 0x40},
{{0}, 5, 11, 0x20},
{{0}, 4, 12, 0x10},
{{0}, 3, 13, 8},
{{0}, 2, 14, 4},
{{0}, 1, 15, 2}},
{1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0, 0x80, 0x40, 0x20, 0x10, 8, 4,
2}},
};
for (auto &&T : BABTests) {
ByteArrayBuilder BABuilder;
for (auto &&A : T.Allocs) {
uint64_t GotByteOffset;
uint8_t GotMask;
BABuilder.allocate(A.Bits, A.BitSize, GotByteOffset, GotMask);
EXPECT_EQ(A.WantByteOffset, GotByteOffset);
EXPECT_EQ(A.WantMask, GotMask);
}
EXPECT_EQ(T.WantBytes, BABuilder.Bytes);
}
}

View File

@ -1,165 +0,0 @@
//===- WholeProgramDevirt.cpp - Unit tests for whole-program devirt -------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/WholeProgramDevirt.h"
#include "llvm/ADT/ArrayRef.h"
#include "gtest/gtest.h"
using namespace llvm;
using namespace wholeprogramdevirt;
TEST(WholeProgramDevirt, findLowestOffset) {
VTableBits VT1;
VT1.ObjectSize = 8;
VT1.Before.BytesUsed = {1 << 0};
VT1.After.BytesUsed = {1 << 1};
VTableBits VT2;
VT2.ObjectSize = 8;
VT2.Before.BytesUsed = {1 << 1};
VT2.After.BytesUsed = {1 << 0};
TypeMemberInfo TM1{&VT1, 0};
TypeMemberInfo TM2{&VT2, 0};
VirtualCallTarget Targets[] = {
{&TM1, /*IsBigEndian=*/false},
{&TM2, /*IsBigEndian=*/false},
};
EXPECT_EQ(2ull, findLowestOffset(Targets, /*IsAfter=*/false, 1));
EXPECT_EQ(66ull, findLowestOffset(Targets, /*IsAfter=*/true, 1));
EXPECT_EQ(8ull, findLowestOffset(Targets, /*IsAfter=*/false, 8));
EXPECT_EQ(72ull, findLowestOffset(Targets, /*IsAfter=*/true, 8));
TM1.Offset = 4;
EXPECT_EQ(33ull, findLowestOffset(Targets, /*IsAfter=*/false, 1));
EXPECT_EQ(65ull, findLowestOffset(Targets, /*IsAfter=*/true, 1));
EXPECT_EQ(40ull, findLowestOffset(Targets, /*IsAfter=*/false, 8));
EXPECT_EQ(72ull, findLowestOffset(Targets, /*IsAfter=*/true, 8));
TM1.Offset = 8;
TM2.Offset = 8;
EXPECT_EQ(66ull, findLowestOffset(Targets, /*IsAfter=*/false, 1));
EXPECT_EQ(2ull, findLowestOffset(Targets, /*IsAfter=*/true, 1));
EXPECT_EQ(72ull, findLowestOffset(Targets, /*IsAfter=*/false, 8));
EXPECT_EQ(8ull, findLowestOffset(Targets, /*IsAfter=*/true, 8));
VT1.After.BytesUsed = {0xff, 0, 0, 0, 0xff};
VT2.After.BytesUsed = {0xff, 1, 0, 0, 0};
EXPECT_EQ(16ull, findLowestOffset(Targets, /*IsAfter=*/true, 16));
EXPECT_EQ(40ull, findLowestOffset(Targets, /*IsAfter=*/true, 32));
}
TEST(WholeProgramDevirt, setReturnValues) {
VTableBits VT1;
VT1.ObjectSize = 8;
VTableBits VT2;
VT2.ObjectSize = 8;
TypeMemberInfo TM1{&VT1, 0};
TypeMemberInfo TM2{&VT2, 0};
VirtualCallTarget Targets[] = {
{&TM1, /*IsBigEndian=*/false},
{&TM2, /*IsBigEndian=*/false},
};
TM1.Offset = 4;
TM2.Offset = 4;
int64_t OffsetByte;
uint64_t OffsetBit;
Targets[0].RetVal = 1;
Targets[1].RetVal = 0;
setBeforeReturnValues(Targets, 32, 1, OffsetByte, OffsetBit);
EXPECT_EQ(-5ll, OffsetByte);
EXPECT_EQ(0ull, OffsetBit);
EXPECT_EQ(std::vector<uint8_t>{1}, VT1.Before.Bytes);
EXPECT_EQ(std::vector<uint8_t>{1}, VT1.Before.BytesUsed);
EXPECT_EQ(std::vector<uint8_t>{0}, VT2.Before.Bytes);
EXPECT_EQ(std::vector<uint8_t>{1}, VT2.Before.BytesUsed);
Targets[0].RetVal = 0;
Targets[1].RetVal = 1;
setBeforeReturnValues(Targets, 39, 1, OffsetByte, OffsetBit);
EXPECT_EQ(-5ll, OffsetByte);
EXPECT_EQ(7ull, OffsetBit);
EXPECT_EQ(std::vector<uint8_t>{1}, VT1.Before.Bytes);
EXPECT_EQ(std::vector<uint8_t>{0x81}, VT1.Before.BytesUsed);
EXPECT_EQ(std::vector<uint8_t>{0x80}, VT2.Before.Bytes);
EXPECT_EQ(std::vector<uint8_t>{0x81}, VT2.Before.BytesUsed);
Targets[0].RetVal = 12;
Targets[1].RetVal = 34;
setBeforeReturnValues(Targets, 40, 8, OffsetByte, OffsetBit);
EXPECT_EQ(-6ll, OffsetByte);
EXPECT_EQ(0ull, OffsetBit);
EXPECT_EQ((std::vector<uint8_t>{1, 12}), VT1.Before.Bytes);
EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff}), VT1.Before.BytesUsed);
EXPECT_EQ((std::vector<uint8_t>{0x80, 34}), VT2.Before.Bytes);
EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff}), VT2.Before.BytesUsed);
Targets[0].RetVal = 56;
Targets[1].RetVal = 78;
setBeforeReturnValues(Targets, 48, 16, OffsetByte, OffsetBit);
EXPECT_EQ(-8ll, OffsetByte);
EXPECT_EQ(0ull, OffsetBit);
EXPECT_EQ((std::vector<uint8_t>{1, 12, 0, 56}), VT1.Before.Bytes);
EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff, 0xff, 0xff}),
VT1.Before.BytesUsed);
EXPECT_EQ((std::vector<uint8_t>{0x80, 34, 0, 78}), VT2.Before.Bytes);
EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff, 0xff, 0xff}),
VT2.Before.BytesUsed);
Targets[0].RetVal = 1;
Targets[1].RetVal = 0;
setAfterReturnValues(Targets, 32, 1, OffsetByte, OffsetBit);
EXPECT_EQ(4ll, OffsetByte);
EXPECT_EQ(0ull, OffsetBit);
EXPECT_EQ(std::vector<uint8_t>{1}, VT1.After.Bytes);
EXPECT_EQ(std::vector<uint8_t>{1}, VT1.After.BytesUsed);
EXPECT_EQ(std::vector<uint8_t>{0}, VT2.After.Bytes);
EXPECT_EQ(std::vector<uint8_t>{1}, VT2.After.BytesUsed);
Targets[0].RetVal = 0;
Targets[1].RetVal = 1;
setAfterReturnValues(Targets, 39, 1, OffsetByte, OffsetBit);
EXPECT_EQ(4ll, OffsetByte);
EXPECT_EQ(7ull, OffsetBit);
EXPECT_EQ(std::vector<uint8_t>{1}, VT1.After.Bytes);
EXPECT_EQ(std::vector<uint8_t>{0x81}, VT1.After.BytesUsed);
EXPECT_EQ(std::vector<uint8_t>{0x80}, VT2.After.Bytes);
EXPECT_EQ(std::vector<uint8_t>{0x81}, VT2.After.BytesUsed);
Targets[0].RetVal = 12;
Targets[1].RetVal = 34;
setAfterReturnValues(Targets, 40, 8, OffsetByte, OffsetBit);
EXPECT_EQ(5ll, OffsetByte);
EXPECT_EQ(0ull, OffsetBit);
EXPECT_EQ((std::vector<uint8_t>{1, 12}), VT1.After.Bytes);
EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff}), VT1.After.BytesUsed);
EXPECT_EQ((std::vector<uint8_t>{0x80, 34}), VT2.After.Bytes);
EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff}), VT2.After.BytesUsed);
Targets[0].RetVal = 56;
Targets[1].RetVal = 78;
setAfterReturnValues(Targets, 48, 16, OffsetByte, OffsetBit);
EXPECT_EQ(6ll, OffsetByte);
EXPECT_EQ(0ull, OffsetBit);
EXPECT_EQ((std::vector<uint8_t>{1, 12, 56, 0}), VT1.After.Bytes);
EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff, 0xff, 0xff}),
VT1.After.BytesUsed);
EXPECT_EQ((std::vector<uint8_t>{0x80, 34, 78, 0}), VT2.After.Bytes);
EXPECT_EQ((std::vector<uint8_t>{0x81, 0xff, 0xff, 0xff}),
VT2.After.BytesUsed);
}

View File

@ -1,12 +0,0 @@
set(LLVM_LINK_COMPONENTS
Analysis
AsmParser
Core
Support
ScalarOpts
TransformUtils
)
add_llvm_unittest(ScalarTests
LoopPassManagerTest.cpp
)

File diff suppressed because it is too large Load Diff

View File

@ -1,135 +0,0 @@
//===- 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;
case kAsanStackUseAfterScopeMagic:
os << "S";
break;
default: os << (unsigned)ShadowBytes[i];
}
}
return os.str();
}
// Use macro to preserve line information in EXPECT_EQ output.
#define TEST_LAYOUT(V, Granularity, MinHeaderSize, ExpectedDescr, \
ExpectedShadow, ExpectedShadowAfterScope) \
{ \
SmallVector<ASanStackVariableDescription, 10> Vars = V; \
ASanStackFrameLayout L = \
ComputeASanStackFrameLayout(Vars, Granularity, MinHeaderSize); \
EXPECT_STREQ(ExpectedDescr, \
ComputeASanStackFrameDescription(Vars).c_str()); \
EXPECT_EQ(ExpectedShadow, ShadowBytesToString(GetShadowBytes(Vars, L))); \
EXPECT_EQ(ExpectedShadowAfterScope, \
ShadowBytesToString(GetShadowBytesAfterScope(Vars, L))); \
}
TEST(ASanStackFrameLayout, Test) {
#define VAR(name, size, lifetime, alignment, line) \
ASanStackVariableDescription name##size##_##alignment = { \
#name #size "_" #alignment, \
size, \
lifetime, \
alignment, \
0, \
0, \
line, \
}
VAR(a, 1, 0, 1, 0);
VAR(p, 1, 0, 32, 15);
VAR(p, 1, 0, 256, 2700);
VAR(a, 2, 0, 1, 0);
VAR(a, 3, 0, 1, 0);
VAR(a, 4, 0, 1, 0);
VAR(a, 7, 0, 1, 0);
VAR(a, 8, 8, 1, 0);
VAR(a, 9, 0, 1, 0);
VAR(a, 16, 16, 1, 0);
VAR(a, 41, 9, 1, 7);
VAR(a, 105, 103, 1, 0);
VAR(a, 200, 97, 1, 0);
TEST_LAYOUT({a1_1}, 8, 16, "1 16 1 4 a1_1", "LL1R", "LL1R");
TEST_LAYOUT({a1_1}, 16, 16, "1 16 1 4 a1_1", "L1R", "L1R");
TEST_LAYOUT({a1_1}, 32, 32, "1 32 1 4 a1_1", "L1R", "L1R");
TEST_LAYOUT({a1_1}, 64, 64, "1 64 1 4 a1_1", "L1R", "L1R");
TEST_LAYOUT({p1_32}, 8, 32, "1 32 1 8 p1_32:15", "LLLL1RRR", "LLLL1RRR");
TEST_LAYOUT({p1_32}, 8, 64, "1 64 1 8 p1_32:15", "LLLLLLLL1RRRRRRR",
"LLLLLLLL1RRRRRRR");
TEST_LAYOUT({a1_1}, 8, 32, "1 32 1 4 a1_1", "LLLL1RRR", "LLLL1RRR");
TEST_LAYOUT({a2_1}, 8, 32, "1 32 2 4 a2_1", "LLLL2RRR", "LLLL2RRR");
TEST_LAYOUT({a3_1}, 8, 32, "1 32 3 4 a3_1", "LLLL3RRR", "LLLL3RRR");
TEST_LAYOUT({a4_1}, 8, 32, "1 32 4 4 a4_1", "LLLL4RRR", "LLLL4RRR");
TEST_LAYOUT({a7_1}, 8, 32, "1 32 7 4 a7_1", "LLLL7RRR", "LLLL7RRR");
TEST_LAYOUT({a8_1}, 8, 32, "1 32 8 4 a8_1", "LLLL0RRR", "LLLLSRRR");
TEST_LAYOUT({a9_1}, 8, 32, "1 32 9 4 a9_1", "LLLL01RR", "LLLL01RR");
TEST_LAYOUT({a16_1}, 8, 32, "1 32 16 5 a16_1", "LLLL00RR", "LLLLSSRR");
TEST_LAYOUT({p1_256}, 8, 32, "1 256 1 11 p1_256:2700",
"LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR",
"LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR");
TEST_LAYOUT({a41_1}, 8, 32, "1 32 41 7 a41_1:7", "LLLL000001RRRRRR",
"LLLLSS0001RRRRRR");
TEST_LAYOUT({a105_1}, 8, 32, "1 32 105 6 a105_1", "LLLL00000000000001RRRRRR",
"LLLLSSSSSSSSSSSSS1RRRRRR");
{
SmallVector<ASanStackVariableDescription, 10> t = {a1_1, p1_256};
TEST_LAYOUT(t, 8, 32, "2 256 1 11 p1_256:2700 272 1 4 a1_1",
"LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1M1R",
"LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1M1R");
}
{
SmallVector<ASanStackVariableDescription, 10> t = {a1_1, a16_1, a41_1};
TEST_LAYOUT(t, 8, 32, "3 32 1 4 a1_1 48 16 5 a16_1 80 41 7 a41_1:7",
"LLLL1M00MM000001RRRR", "LLLL1MSSMMSS0001RRRR");
}
TEST_LAYOUT({a2_1}, 32, 32, "1 32 2 4 a2_1", "L2R", "L2R");
TEST_LAYOUT({a9_1}, 32, 32, "1 32 9 4 a9_1", "L9R", "L9R");
TEST_LAYOUT({a16_1}, 32, 32, "1 32 16 5 a16_1", "L16R", "LSR");
TEST_LAYOUT({p1_256}, 32, 32, "1 256 1 11 p1_256:2700",
"LLLLLLLL1R", "LLLLLLLL1R");
TEST_LAYOUT({a41_1}, 32, 32, "1 32 41 7 a41_1:7", "L09R",
"LS9R");
TEST_LAYOUT({a105_1}, 32, 32, "1 32 105 6 a105_1", "L0009R",
"LSSSSR");
TEST_LAYOUT({a200_1}, 32, 32, "1 32 200 6 a200_1", "L0000008RR",
"LSSSS008RR");
{
SmallVector<ASanStackVariableDescription, 10> t = {a1_1, p1_256};
TEST_LAYOUT(t, 32, 32, "2 256 1 11 p1_256:2700 320 1 4 a1_1",
"LLLLLLLL1M1R", "LLLLLLLL1M1R");
}
{
SmallVector<ASanStackVariableDescription, 10> t = {a1_1, a16_1, a41_1};
TEST_LAYOUT(t, 32, 32, "3 32 1 4 a1_1 96 16 5 a16_1 160 41 7 a41_1:7",
"L1M16M09R", "L1MSMS9R");
}
#undef VAR
#undef TEST_LAYOUT
}

View File

@ -1,18 +0,0 @@
set(LLVM_LINK_COMPONENTS
Analysis
AsmParser
Core
Support
TransformUtils
)
add_llvm_unittest(UtilsTests
ASanStackFrameLayoutTest.cpp
Cloning.cpp
CodeExtractor.cpp
FunctionComparator.cpp
IntegerDivision.cpp
Local.cpp
OrderedInstructions.cpp
ValueMapperTest.cpp
)

File diff suppressed because it is too large Load Diff

View File

@ -1,69 +0,0 @@
//===- CodeExtractor.cpp - Unit tests for CodeExtractor -------------------===//
//
// 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/CodeExtractor.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
TEST(CodeExtractor, ExitStub) {
LLVMContext Ctx;
SMDiagnostic Err;
std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
define i32 @foo(i32 %x, i32 %y, i32 %z) {
header:
%0 = icmp ugt i32 %x, %y
br i1 %0, label %body1, label %body2
body1:
%1 = add i32 %z, 2
br label %notExtracted
body2:
%2 = mul i32 %z, 7
br label %notExtracted
notExtracted:
%3 = phi i32 [ %1, %body1 ], [ %2, %body2 ]
%4 = add i32 %3, %x
ret i32 %4
}
)invalid",
Err, Ctx));
Function *Func = M->getFunction("foo");
SmallVector<BasicBlock *, 3> Candidates;
for (auto &BB : *Func) {
if (BB.getName() == "body1")
Candidates.push_back(&BB);
if (BB.getName() == "body2")
Candidates.push_back(&BB);
}
// CodeExtractor requires the first basic block
// to dominate all the other ones.
Candidates.insert(Candidates.begin(), &Func->getEntryBlock());
DominatorTree DT(*Func);
CodeExtractor CE(Candidates, &DT);
EXPECT_TRUE(CE.isEligible());
Function *Outlined = CE.extractCodeRegion();
EXPECT_TRUE(Outlined);
EXPECT_FALSE(verifyFunction(*Outlined));
}
} // end anonymous namespace

View File

@ -1,130 +0,0 @@
//===- FunctionComparator.cpp - Unit tests for FunctionComparator ---------===//
//
// 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/FunctionComparator.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "gtest/gtest.h"
using namespace llvm;
/// Generates a simple test function.
struct TestFunction {
Function *F;
BasicBlock *BB;
Constant *C;
Instruction *I;
Type *T;
TestFunction(LLVMContext &Ctx, Module &M, int addVal) {
IRBuilder<> B(Ctx);
T = B.getInt8Ty();
F = Function::Create(FunctionType::get(T, {B.getInt8PtrTy()}, false),
GlobalValue::ExternalLinkage, "F", &M);
BB = BasicBlock::Create(Ctx, "", F);
B.SetInsertPoint(BB);
Argument *PointerArg = &*F->arg_begin();
LoadInst *LoadInst = B.CreateLoad(PointerArg);
C = B.getInt8(addVal);
I = cast<Instruction>(B.CreateAdd(LoadInst, C));
B.CreateRet(I);
}
};
/// A class for testing the FunctionComparator API.
///
/// The main purpose is to test if the required protected functions are
/// accessible from a derived class of FunctionComparator.
class TestComparator : public FunctionComparator {
public:
TestComparator(const Function *F1, const Function *F2,
GlobalNumberState *GN)
: FunctionComparator(F1, F2, GN) {
}
bool testFunctionAccess(const Function *F1, const Function *F2) {
// Test if FnL and FnR are accessible.
return F1 == FnL && F2 == FnR;
}
int testCompare() {
return compare();
}
int testCompareSignature() {
beginCompare();
return compareSignature();
}
int testCmpBasicBlocks(BasicBlock *BBL, BasicBlock *BBR) {
beginCompare();
return cmpBasicBlocks(BBL, BBR);
}
int testCmpConstants(const Constant *L, const Constant *R) {
beginCompare();
return cmpConstants(L, R);
}
int testCmpGlobalValues(GlobalValue *L, GlobalValue *R) {
beginCompare();
return cmpGlobalValues(L, R);
}
int testCmpValues(const Value *L, const Value *R) {
beginCompare();
return cmpValues(L, R);
}
int testCmpOperations(const Instruction *L, const Instruction *R,
bool &needToCmpOperands) {
beginCompare();
return cmpOperations(L, R, needToCmpOperands);
}
int testCmpTypes(Type *TyL, Type *TyR) {
beginCompare();
return cmpTypes(TyL, TyR);
}
int testCmpPrimitives() {
beginCompare();
return
cmpNumbers(2, 3) +
cmpAPInts(APInt(32, 2), APInt(32, 3)) +
cmpAPFloats(APFloat(2.0), APFloat(3.0)) +
cmpMem("2", "3");
}
};
/// A sanity check for the FunctionComparator API.
TEST(FunctionComparatorTest, TestAPI) {
LLVMContext C;
Module M("test", C);
TestFunction F1(C, M, 27);
TestFunction F2(C, M, 28);
GlobalNumberState GN;
TestComparator Cmp(F1.F, F2.F, &GN);
EXPECT_TRUE(Cmp.testFunctionAccess(F1.F, F2.F));
EXPECT_EQ(Cmp.testCompare(), -1);
EXPECT_EQ(Cmp.testCompareSignature(), 0);
EXPECT_EQ(Cmp.testCmpBasicBlocks(F1.BB, F2.BB), -1);
EXPECT_EQ(Cmp.testCmpConstants(F1.C, F2.C), -1);
EXPECT_EQ(Cmp.testCmpGlobalValues(F1.F, F2.F), -1);
EXPECT_EQ(Cmp.testCmpValues(F1.I, F2.I), 0);
bool needToCmpOperands = false;
EXPECT_EQ(Cmp.testCmpOperations(F1.I, F2.I, needToCmpOperands), 0);
EXPECT_TRUE(needToCmpOperands);
EXPECT_EQ(Cmp.testCmpTypes(F1.T, F2.T), 0);
EXPECT_EQ(Cmp.testCmpPrimitives(), -4);
}

View File

@ -1,264 +0,0 @@
//===- IntegerDivision.cpp - Unit tests for the integer division code -----===//
//
// 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/IntegerDivision.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
TEST(IntegerDivision, SDiv) {
LLVMContext C;
Module M("test division", C);
IRBuilder<> Builder(C);
SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
ArgTys, false),
GlobalValue::ExternalLinkage, "F", &M);
assert(F->arg_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, UDiv) {
LLVMContext C;
Module M("test division", C);
IRBuilder<> Builder(C);
SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
ArgTys, false),
GlobalValue::ExternalLinkage, "F", &M);
assert(F->arg_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, SRem) {
LLVMContext C;
Module M("test remainder", C);
IRBuilder<> Builder(C);
SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
ArgTys, false),
GlobalValue::ExternalLinkage, "F", &M);
assert(F->arg_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, URem) {
LLVMContext C;
Module M("test remainder", C);
IRBuilder<> Builder(C);
SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
ArgTys, false),
GlobalValue::ExternalLinkage, "F", &M);
assert(F->arg_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);
}
TEST(IntegerDivision, SDiv64) {
LLVMContext C;
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->arg_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;
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->arg_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;
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->arg_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;
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->arg_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);
}
}

View File

@ -1,214 +0,0 @@
//===- Local.cpp - Unit tests for Local -----------------------------------===//
//
// 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/Local.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
TEST(Local, RecursivelyDeleteDeadPHINodes) {
LLVMContext C;
IRBuilder<> builder(C);
// Make blocks
BasicBlock *bb0 = BasicBlock::Create(C);
BasicBlock *bb1 = BasicBlock::Create(C);
builder.SetInsertPoint(bb0);
PHINode *phi = builder.CreatePHI(Type::getInt32Ty(C), 2);
BranchInst *br0 = builder.CreateCondBr(builder.getTrue(), bb0, bb1);
builder.SetInsertPoint(bb1);
BranchInst *br1 = builder.CreateBr(bb0);
phi->addIncoming(phi, bb0);
phi->addIncoming(phi, bb1);
// The PHI will be removed
EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));
// Make sure the blocks only contain the branches
EXPECT_EQ(&bb0->front(), br0);
EXPECT_EQ(&bb1->front(), br1);
builder.SetInsertPoint(bb0);
phi = builder.CreatePHI(Type::getInt32Ty(C), 0);
EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));
builder.SetInsertPoint(bb0);
phi = builder.CreatePHI(Type::getInt32Ty(C), 0);
builder.CreateAdd(phi, phi);
EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));
bb0->dropAllReferences();
bb1->dropAllReferences();
delete bb0;
delete bb1;
}
TEST(Local, RemoveDuplicatePHINodes) {
LLVMContext C;
IRBuilder<> B(C);
std::unique_ptr<Function> F(
Function::Create(FunctionType::get(B.getVoidTy(), false),
GlobalValue::ExternalLinkage, "F"));
BasicBlock *Entry(BasicBlock::Create(C, "", F.get()));
BasicBlock *BB(BasicBlock::Create(C, "", F.get()));
BranchInst::Create(BB, Entry);
B.SetInsertPoint(BB);
AssertingVH<PHINode> P1 = B.CreatePHI(Type::getInt32Ty(C), 2);
P1->addIncoming(B.getInt32(42), Entry);
PHINode *P2 = B.CreatePHI(Type::getInt32Ty(C), 2);
P2->addIncoming(B.getInt32(42), Entry);
AssertingVH<PHINode> P3 = B.CreatePHI(Type::getInt32Ty(C), 2);
P3->addIncoming(B.getInt32(42), Entry);
P3->addIncoming(B.getInt32(23), BB);
PHINode *P4 = B.CreatePHI(Type::getInt32Ty(C), 2);
P4->addIncoming(B.getInt32(42), Entry);
P4->addIncoming(B.getInt32(23), BB);
P1->addIncoming(P3, BB);
P2->addIncoming(P4, BB);
BranchInst::Create(BB, BB);
// Verify that we can eliminate PHIs that become duplicates after chaning PHIs
// downstream.
EXPECT_TRUE(EliminateDuplicatePHINodes(BB));
EXPECT_EQ(3U, BB->size());
}
std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
SMDiagnostic Err;
std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
if (!Mod)
Err.print("UtilsTests", errs());
return Mod;
}
TEST(Local, ReplaceDbgDeclare) {
LLVMContext C;
// Original C source to get debug info for a local variable:
// void f() { int x; }
std::unique_ptr<Module> M = parseIR(
C,
"define void @f() !dbg !8 {\n"
"entry:\n"
" %x = alloca i32, align 4\n"
" call void @llvm.dbg.declare(metadata i32* %x, metadata !11, metadata "
"!DIExpression()), !dbg !13\n"
" call void @llvm.dbg.declare(metadata i32* %x, metadata !11, metadata "
"!DIExpression()), !dbg !13\n"
" ret void, !dbg !14\n"
"}\n"
"declare void @llvm.dbg.declare(metadata, metadata, metadata)\n"
"!llvm.dbg.cu = !{!0}\n"
"!llvm.module.flags = !{!3, !4}\n"
"!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "
"\"clang version 6.0.0 \", isOptimized: false, runtimeVersion: 0, "
"emissionKind: FullDebug, enums: !2)\n"
"!1 = !DIFile(filename: \"t2.c\", directory: \"foo\")\n"
"!2 = !{}\n"
"!3 = !{i32 2, !\"Dwarf Version\", i32 4}\n"
"!4 = !{i32 2, !\"Debug Info Version\", i32 3}\n"
"!8 = distinct !DISubprogram(name: \"f\", scope: !1, file: !1, line: 1, "
"type: !9, isLocal: false, isDefinition: true, scopeLine: 1, "
"isOptimized: false, unit: !0, variables: !2)\n"
"!9 = !DISubroutineType(types: !10)\n"
"!10 = !{null}\n"
"!11 = !DILocalVariable(name: \"x\", scope: !8, file: !1, line: 2, type: "
"!12)\n"
"!12 = !DIBasicType(name: \"int\", size: 32, encoding: DW_ATE_signed)\n"
"!13 = !DILocation(line: 2, column: 7, scope: !8)\n"
"!14 = !DILocation(line: 3, column: 1, scope: !8)\n");
auto *GV = M->getNamedValue("f");
ASSERT_TRUE(GV);
auto *F = dyn_cast<Function>(GV);
ASSERT_TRUE(F);
Instruction *Inst = &F->front().front();
auto *AI = dyn_cast<AllocaInst>(Inst);
ASSERT_TRUE(AI);
Inst = Inst->getNextNode()->getNextNode();
ASSERT_TRUE(Inst);
auto *DII = dyn_cast<DbgDeclareInst>(Inst);
ASSERT_TRUE(DII);
Value *NewBase = Constant::getNullValue(Type::getInt32PtrTy(C));
DIBuilder DIB(*M);
replaceDbgDeclare(AI, NewBase, DII, DIB, DIExpression::NoDeref, 0,
DIExpression::NoDeref);
// There should be exactly two dbg.declares.
int Declares = 0;
for (const Instruction &I : F->front())
if (isa<DbgDeclareInst>(I))
Declares++;
EXPECT_EQ(2, Declares);
}
/// Build the dominator tree for the function and run the Test.
static void runWithDomTree(
Module &M, StringRef FuncName,
function_ref<void(Function &F, DominatorTree *DT)> Test) {
auto *F = M.getFunction(FuncName);
ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
// Compute the dominator tree for the function.
DominatorTree DT(*F);
Test(*F, &DT);
}
TEST(Local, MergeBasicBlockIntoOnlyPred) {
LLVMContext C;
std::unique_ptr<Module> M = parseIR(
C,
"define i32 @f(i8* %str) {\n"
"entry:\n"
" br label %bb2.i\n"
"bb2.i: ; preds = %bb4.i, %entry\n"
" br i1 false, label %bb4.i, label %base2flt.exit204\n"
"bb4.i: ; preds = %bb2.i\n"
" br i1 false, label %base2flt.exit204, label %bb2.i\n"
"bb10.i196.bb7.i197_crit_edge: ; No predecessors!\n"
" br label %bb7.i197\n"
"bb7.i197: ; preds = %bb10.i196.bb7.i197_crit_edge\n"
" %.reg2mem.0 = phi i32 [ %.reg2mem.0, %bb10.i196.bb7.i197_crit_edge ]\n"
" br i1 undef, label %base2flt.exit204, label %base2flt.exit204\n"
"base2flt.exit204: ; preds = %bb7.i197, %bb7.i197, %bb2.i, %bb4.i\n"
" ret i32 0\n"
"}\n");
runWithDomTree(
*M, "f", [&](Function &F, DominatorTree *DT) {
for (Function::iterator I = F.begin(), E = F.end(); I != E;) {
BasicBlock *BB = &*I++;
BasicBlock *SinglePred = BB->getSinglePredecessor();
if (!SinglePred || SinglePred == BB || BB->hasAddressTaken()) continue;
BranchInst *Term = dyn_cast<BranchInst>(SinglePred->getTerminator());
if (Term && !Term->isConditional())
MergeBasicBlockIntoOnlyPred(BB, DT);
}
EXPECT_TRUE(DT->verify());
});
}

View File

@ -1,65 +0,0 @@
//===- OrderedInstructions.cpp - Unit tests for OrderedInstructions ------===//
//
// 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/OrderedInstructions.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "gtest/gtest.h"
using namespace llvm;
/// Check intra-basicblock and inter-basicblock dominance using
/// OrderedInstruction.
TEST(OrderedInstructionsTest, DominanceTest) {
LLVMContext Ctx;
Module M("test", Ctx);
IRBuilder<> B(Ctx);
FunctionType *FTy =
FunctionType::get(Type::getVoidTy(Ctx), {B.getInt8PtrTy()}, false);
Function *F = cast<Function>(M.getOrInsertFunction("f", FTy));
// Create the function as follow and check for dominance relation.
//
// test():
// bbx:
// loadx;
// loady;
// bby:
// loadz;
// return;
//
// More specifically, check for loadx -> (dominates) loady,
// loady -> loadx and loady -> loadz.
//
// Create BBX with 2 loads.
BasicBlock *BBX = BasicBlock::Create(Ctx, "bbx", F);
B.SetInsertPoint(BBX);
Argument *PointerArg = &*F->arg_begin();
LoadInst *LoadInstX = B.CreateLoad(PointerArg);
LoadInst *LoadInstY = B.CreateLoad(PointerArg);
// Create BBY with 1 load.
BasicBlock *BBY = BasicBlock::Create(Ctx, "bby", F);
B.SetInsertPoint(BBY);
LoadInst *LoadInstZ = B.CreateLoad(PointerArg);
B.CreateRet(LoadInstZ);
std::unique_ptr<DominatorTree> DT(new DominatorTree(*F));
OrderedInstructions OI(&*DT);
// Intra-BB dominance test.
EXPECT_TRUE(OI.dominates(LoadInstX, LoadInstY));
EXPECT_FALSE(OI.dominates(LoadInstY, LoadInstX));
// Inter-BB dominance test.
EXPECT_TRUE(OI.dominates(LoadInstY, LoadInstZ));
}

View File

@ -1,350 +0,0 @@
//===- ValueMapper.cpp - Unit tests for ValueMapper -----------------------===//
//
// 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/ValueMapper.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "gtest/gtest.h"
using namespace llvm;
namespace {
TEST(ValueMapperTest, mapMDNode) {
LLVMContext Context;
auto *U = MDTuple::get(Context, None);
// The node should be unchanged.
ValueToValueMapTy VM;
EXPECT_EQ(U, ValueMapper(VM).mapMDNode(*U));
}
TEST(ValueMapperTest, mapMDNodeCycle) {
LLVMContext Context;
MDNode *U0;
MDNode *U1;
{
Metadata *Ops[] = {nullptr};
auto T = MDTuple::getTemporary(Context, Ops);
Ops[0] = T.get();
U0 = MDTuple::get(Context, Ops);
T->replaceOperandWith(0, U0);
U1 = MDNode::replaceWithUniqued(std::move(T));
U0->resolveCycles();
}
EXPECT_TRUE(U0->isResolved());
EXPECT_TRUE(U0->isUniqued());
EXPECT_TRUE(U1->isResolved());
EXPECT_TRUE(U1->isUniqued());
EXPECT_EQ(U1, U0->getOperand(0));
EXPECT_EQ(U0, U1->getOperand(0));
// Cycles shouldn't be duplicated.
{
ValueToValueMapTy VM;
EXPECT_EQ(U0, ValueMapper(VM).mapMDNode(*U0));
EXPECT_EQ(U1, ValueMapper(VM).mapMDNode(*U1));
}
// Check the other order.
{
ValueToValueMapTy VM;
EXPECT_EQ(U1, ValueMapper(VM).mapMDNode(*U1));
EXPECT_EQ(U0, ValueMapper(VM).mapMDNode(*U0));
}
}
TEST(ValueMapperTest, mapMDNodeDuplicatedCycle) {
LLVMContext Context;
auto *PtrTy = Type::getInt8Ty(Context)->getPointerTo();
std::unique_ptr<GlobalVariable> G0 = llvm::make_unique<GlobalVariable>(
PtrTy, false, GlobalValue::ExternalLinkage, nullptr, "G0");
std::unique_ptr<GlobalVariable> G1 = llvm::make_unique<GlobalVariable>(
PtrTy, false, GlobalValue::ExternalLinkage, nullptr, "G1");
// Create a cycle that references G0.
MDNode *N0; // !0 = !{!1}
MDNode *N1; // !1 = !{!0, i8* @G0}
{
auto T0 = MDTuple::getTemporary(Context, nullptr);
Metadata *Ops1[] = {T0.get(), ConstantAsMetadata::get(G0.get())};
N1 = MDTuple::get(Context, Ops1);
T0->replaceOperandWith(0, N1);
N0 = MDNode::replaceWithUniqued(std::move(T0));
}
// Resolve N0 and N1.
ASSERT_FALSE(N0->isResolved());
ASSERT_FALSE(N1->isResolved());
N0->resolveCycles();
ASSERT_TRUE(N0->isResolved());
ASSERT_TRUE(N1->isResolved());
// Seed the value map to map G0 to G1 and map the nodes. The output should
// have new nodes that reference G1 (instead of G0).
ValueToValueMapTy VM;
VM[G0.get()] = G1.get();
MDNode *MappedN0 = ValueMapper(VM).mapMDNode(*N0);
MDNode *MappedN1 = ValueMapper(VM).mapMDNode(*N1);
EXPECT_NE(N0, MappedN0);
EXPECT_NE(N1, MappedN1);
EXPECT_EQ(ConstantAsMetadata::get(G1.get()), MappedN1->getOperand(1));
// Check that the output nodes are resolved.
EXPECT_TRUE(MappedN0->isResolved());
EXPECT_TRUE(MappedN1->isResolved());
}
TEST(ValueMapperTest, mapMDNodeUnresolved) {
LLVMContext Context;
TempMDTuple T = MDTuple::getTemporary(Context, None);
ValueToValueMapTy VM;
EXPECT_EQ(T.get(), ValueMapper(VM, RF_NoModuleLevelChanges).mapMDNode(*T));
}
TEST(ValueMapperTest, mapMDNodeDistinct) {
LLVMContext Context;
auto *D = MDTuple::getDistinct(Context, None);
{
// The node should be cloned.
ValueToValueMapTy VM;
EXPECT_NE(D, ValueMapper(VM).mapMDNode(*D));
}
{
// The node should be moved.
ValueToValueMapTy VM;
EXPECT_EQ(D, ValueMapper(VM, RF_MoveDistinctMDs).mapMDNode(*D));
}
}
TEST(ValueMapperTest, mapMDNodeDistinctOperands) {
LLVMContext Context;
Metadata *Old = MDTuple::getDistinct(Context, None);
auto *D = MDTuple::getDistinct(Context, Old);
ASSERT_EQ(Old, D->getOperand(0));
Metadata *New = MDTuple::getDistinct(Context, None);
ValueToValueMapTy VM;
VM.MD()[Old].reset(New);
// Make sure operands are updated.
EXPECT_EQ(D, ValueMapper(VM, RF_MoveDistinctMDs).mapMDNode(*D));
EXPECT_EQ(New, D->getOperand(0));
}
TEST(ValueMapperTest, mapMDNodeSeeded) {
LLVMContext Context;
auto *D = MDTuple::getDistinct(Context, None);
// The node should be moved.
ValueToValueMapTy VM;
EXPECT_EQ(None, VM.getMappedMD(D));
VM.MD().insert(std::make_pair(D, TrackingMDRef(D)));
EXPECT_EQ(D, *VM.getMappedMD(D));
EXPECT_EQ(D, ValueMapper(VM).mapMDNode(*D));
}
TEST(ValueMapperTest, mapMDNodeSeededWithNull) {
LLVMContext Context;
auto *D = MDTuple::getDistinct(Context, None);
// The node should be moved.
ValueToValueMapTy VM;
EXPECT_EQ(None, VM.getMappedMD(D));
VM.MD().insert(std::make_pair(D, TrackingMDRef()));
EXPECT_EQ(nullptr, *VM.getMappedMD(D));
EXPECT_EQ(nullptr, ValueMapper(VM).mapMDNode(*D));
}
TEST(ValueMapperTest, mapMetadataNullMapGlobalWithIgnoreMissingLocals) {
LLVMContext C;
FunctionType *FTy =
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
std::unique_ptr<Function> F(
Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
ValueToValueMapTy VM;
RemapFlags Flags = RF_IgnoreMissingLocals | RF_NullMapMissingGlobalValues;
EXPECT_EQ(nullptr, ValueMapper(VM, Flags).mapValue(*F));
}
TEST(ValueMapperTest, mapMetadataMDString) {
LLVMContext C;
auto *S1 = MDString::get(C, "S1");
ValueToValueMapTy VM;
// Make sure S1 maps to itself, but isn't memoized.
EXPECT_EQ(S1, ValueMapper(VM).mapMetadata(*S1));
EXPECT_EQ(None, VM.getMappedMD(S1));
// We still expect VM.MD() to be respected.
auto *S2 = MDString::get(C, "S2");
VM.MD()[S1].reset(S2);
EXPECT_EQ(S2, ValueMapper(VM).mapMetadata(*S1));
}
TEST(ValueMapperTest, mapMetadataGetMappedMD) {
LLVMContext C;
auto *N0 = MDTuple::get(C, None);
auto *N1 = MDTuple::get(C, N0);
// Make sure hasMD and getMappedMD work correctly.
ValueToValueMapTy VM;
EXPECT_FALSE(VM.hasMD());
EXPECT_EQ(N0, ValueMapper(VM).mapMetadata(*N0));
EXPECT_EQ(N1, ValueMapper(VM).mapMetadata(*N1));
EXPECT_TRUE(VM.hasMD());
ASSERT_NE(None, VM.getMappedMD(N0));
ASSERT_NE(None, VM.getMappedMD(N1));
EXPECT_EQ(N0, *VM.getMappedMD(N0));
EXPECT_EQ(N1, *VM.getMappedMD(N1));
}
TEST(ValueMapperTest, mapMetadataNoModuleLevelChanges) {
LLVMContext C;
auto *N0 = MDTuple::get(C, None);
auto *N1 = MDTuple::get(C, N0);
// Nothing should be memoized when RF_NoModuleLevelChanges.
ValueToValueMapTy VM;
EXPECT_FALSE(VM.hasMD());
EXPECT_EQ(N0, ValueMapper(VM, RF_NoModuleLevelChanges).mapMetadata(*N0));
EXPECT_EQ(N1, ValueMapper(VM, RF_NoModuleLevelChanges).mapMetadata(*N1));
EXPECT_FALSE(VM.hasMD());
EXPECT_EQ(None, VM.getMappedMD(N0));
EXPECT_EQ(None, VM.getMappedMD(N1));
}
TEST(ValueMapperTest, mapMetadataConstantAsMetadata) {
LLVMContext C;
FunctionType *FTy =
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
std::unique_ptr<Function> F(
Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
auto *CAM = ConstantAsMetadata::get(F.get());
{
// ConstantAsMetadata shouldn't be memoized.
ValueToValueMapTy VM;
EXPECT_EQ(CAM, ValueMapper(VM).mapMetadata(*CAM));
EXPECT_FALSE(VM.MD().count(CAM));
EXPECT_EQ(CAM, ValueMapper(VM, RF_IgnoreMissingLocals).mapMetadata(*CAM));
EXPECT_FALSE(VM.MD().count(CAM));
// But it should respect a mapping that gets seeded.
auto *N = MDTuple::get(C, None);
VM.MD()[CAM].reset(N);
EXPECT_EQ(N, ValueMapper(VM).mapMetadata(*CAM));
EXPECT_EQ(N, ValueMapper(VM, RF_IgnoreMissingLocals).mapMetadata(*CAM));
}
std::unique_ptr<Function> F2(
Function::Create(FTy, GlobalValue::ExternalLinkage, "F2"));
ValueToValueMapTy VM;
VM[F.get()] = F2.get();
auto *F2MD = ValueMapper(VM).mapMetadata(*CAM);
EXPECT_FALSE(VM.MD().count(CAM));
EXPECT_TRUE(F2MD);
EXPECT_EQ(F2.get(), cast<ConstantAsMetadata>(F2MD)->getValue());
}
#ifdef GTEST_HAS_DEATH_TEST
#ifndef NDEBUG
TEST(ValueMapperTest, mapMetadataLocalAsMetadata) {
LLVMContext C;
FunctionType *FTy =
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
std::unique_ptr<Function> F(
Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
Argument &A = *F->arg_begin();
// mapMetadata doesn't support LocalAsMetadata. The only valid container for
// LocalAsMetadata is a MetadataAsValue instance, so use it directly.
auto *LAM = LocalAsMetadata::get(&A);
ValueToValueMapTy VM;
EXPECT_DEATH(ValueMapper(VM).mapMetadata(*LAM), "Unexpected local metadata");
EXPECT_DEATH(ValueMapper(VM, RF_IgnoreMissingLocals).mapMetadata(*LAM),
"Unexpected local metadata");
}
#endif
#endif
TEST(ValueMapperTest, mapValueLocalAsMetadata) {
LLVMContext C;
FunctionType *FTy =
FunctionType::get(Type::getVoidTy(C), Type::getInt8Ty(C), false);
std::unique_ptr<Function> F(
Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
Argument &A = *F->arg_begin();
auto *LAM = LocalAsMetadata::get(&A);
auto *MAV = MetadataAsValue::get(C, LAM);
// The principled answer to a LocalAsMetadata of an unmapped SSA value would
// be to return nullptr (regardless of RF_IgnoreMissingLocals).
//
// However, algorithms that use RemapInstruction assume that each instruction
// only references SSA values from previous instructions. Arguments of
// such as "metadata i32 %x" don't currently successfully maintain that
// property. To keep RemapInstruction from crashing we need a non-null
// return here, but we also shouldn't reference the unmapped local. Use
// "metadata !{}".
auto *N0 = MDTuple::get(C, None);
auto *N0AV = MetadataAsValue::get(C, N0);
ValueToValueMapTy VM;
EXPECT_EQ(N0AV, ValueMapper(VM).mapValue(*MAV));
EXPECT_EQ(nullptr, ValueMapper(VM, RF_IgnoreMissingLocals).mapValue(*MAV));
EXPECT_FALSE(VM.count(MAV));
EXPECT_FALSE(VM.count(&A));
EXPECT_EQ(None, VM.getMappedMD(LAM));
VM[MAV] = MAV;
EXPECT_EQ(MAV, ValueMapper(VM).mapValue(*MAV));
EXPECT_EQ(MAV, ValueMapper(VM, RF_IgnoreMissingLocals).mapValue(*MAV));
EXPECT_TRUE(VM.count(MAV));
EXPECT_FALSE(VM.count(&A));
VM[MAV] = &A;
EXPECT_EQ(&A, ValueMapper(VM).mapValue(*MAV));
EXPECT_EQ(&A, ValueMapper(VM, RF_IgnoreMissingLocals).mapValue(*MAV));
EXPECT_TRUE(VM.count(MAV));
EXPECT_FALSE(VM.count(&A));
}
TEST(ValueMapperTest, mapValueLocalAsMetadataToConstant) {
LLVMContext Context;
auto *Int8 = Type::getInt8Ty(Context);
FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), Int8, false);
std::unique_ptr<Function> F(
Function::Create(FTy, GlobalValue::ExternalLinkage, "F"));
// Map a local value to a constant.
Argument &A = *F->arg_begin();
Constant &C = *ConstantInt::get(Int8, 42);
ValueToValueMapTy VM;
VM[&A] = &C;
// Look up the metadata-as-value wrapper. Don't crash.
auto *MDA = MetadataAsValue::get(Context, ValueAsMetadata::get(&A));
auto *MDC = MetadataAsValue::get(Context, ValueAsMetadata::get(&C));
EXPECT_TRUE(isa<LocalAsMetadata>(MDA->getMetadata()));
EXPECT_TRUE(isa<ConstantAsMetadata>(MDC->getMetadata()));
EXPECT_EQ(&C, ValueMapper(VM).mapValue(A));
EXPECT_EQ(MDC, ValueMapper(VM).mapValue(*MDA));
}
} // end namespace