You've already forked linux-packaging-mono
Imported Upstream version 5.18.0.167
Former-commit-id: 289509151e0fee68a1b591a20c9f109c3c789d3a
This commit is contained in:
parent
e19d552987
commit
b084638f15
@ -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
|
||||
}
|
@ -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
|
||||
)
|
617
external/llvm/unittests/Transforms/Utils/Cloning.cpp
vendored
617
external/llvm/unittests/Transforms/Utils/Cloning.cpp
vendored
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
214
external/llvm/unittests/Transforms/Utils/Local.cpp
vendored
214
external/llvm/unittests/Transforms/Utils/Local.cpp
vendored
@ -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());
|
||||
});
|
||||
}
|
@ -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));
|
||||
}
|
@ -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
|
Reference in New Issue
Block a user