1 //===- Cloning.cpp - Unit tests for the Cloner ----------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/SmallPtrSet.h"
12 #include "llvm/IR/Argument.h"
13 #include "llvm/IR/Constant.h"
14 #include "llvm/IR/Function.h"
15 #include "llvm/IR/Instructions.h"
16 #include "llvm/IR/IRBuilder.h"
17 #include "llvm/IR/LLVMContext.h"
18 #include "llvm/Transforms/Utils/Cloning.h"
19 #include "gtest/gtest.h"
20
21 using namespace llvm;
22
23 namespace {
24
25 class CloneInstruction : public ::testing::Test {
26 protected:
SetUp()27 virtual void SetUp() {
28 V = NULL;
29 }
30
31 template <typename T>
clone(T * V1)32 T *clone(T *V1) {
33 Value *V2 = V1->clone();
34 Orig.insert(V1);
35 Clones.insert(V2);
36 return cast<T>(V2);
37 }
38
eraseClones()39 void eraseClones() {
40 DeleteContainerPointers(Clones);
41 }
42
TearDown()43 virtual void TearDown() {
44 eraseClones();
45 DeleteContainerPointers(Orig);
46 delete V;
47 }
48
49 SmallPtrSet<Value *, 4> Orig; // Erase on exit
50 SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones
51
52 LLVMContext context;
53 Value *V;
54 };
55
TEST_F(CloneInstruction,OverflowBits)56 TEST_F(CloneInstruction, OverflowBits) {
57 V = new Argument(Type::getInt32Ty(context));
58
59 BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V);
60 BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V);
61 BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V);
62
63 BinaryOperator *AddClone = this->clone(Add);
64 BinaryOperator *SubClone = this->clone(Sub);
65 BinaryOperator *MulClone = this->clone(Mul);
66
67 EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
68 EXPECT_FALSE(AddClone->hasNoSignedWrap());
69 EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
70 EXPECT_FALSE(SubClone->hasNoSignedWrap());
71 EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
72 EXPECT_FALSE(MulClone->hasNoSignedWrap());
73
74 eraseClones();
75
76 Add->setHasNoUnsignedWrap();
77 Sub->setHasNoUnsignedWrap();
78 Mul->setHasNoUnsignedWrap();
79
80 AddClone = this->clone(Add);
81 SubClone = this->clone(Sub);
82 MulClone = this->clone(Mul);
83
84 EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
85 EXPECT_FALSE(AddClone->hasNoSignedWrap());
86 EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
87 EXPECT_FALSE(SubClone->hasNoSignedWrap());
88 EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
89 EXPECT_FALSE(MulClone->hasNoSignedWrap());
90
91 eraseClones();
92
93 Add->setHasNoSignedWrap();
94 Sub->setHasNoSignedWrap();
95 Mul->setHasNoSignedWrap();
96
97 AddClone = this->clone(Add);
98 SubClone = this->clone(Sub);
99 MulClone = this->clone(Mul);
100
101 EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
102 EXPECT_TRUE(AddClone->hasNoSignedWrap());
103 EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
104 EXPECT_TRUE(SubClone->hasNoSignedWrap());
105 EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
106 EXPECT_TRUE(MulClone->hasNoSignedWrap());
107
108 eraseClones();
109
110 Add->setHasNoUnsignedWrap(false);
111 Sub->setHasNoUnsignedWrap(false);
112 Mul->setHasNoUnsignedWrap(false);
113
114 AddClone = this->clone(Add);
115 SubClone = this->clone(Sub);
116 MulClone = this->clone(Mul);
117
118 EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
119 EXPECT_TRUE(AddClone->hasNoSignedWrap());
120 EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
121 EXPECT_TRUE(SubClone->hasNoSignedWrap());
122 EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
123 EXPECT_TRUE(MulClone->hasNoSignedWrap());
124 }
125
TEST_F(CloneInstruction,Inbounds)126 TEST_F(CloneInstruction, Inbounds) {
127 V = new Argument(Type::getInt32PtrTy(context));
128
129 Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
130 std::vector<Value *> ops;
131 ops.push_back(Z);
132 GetElementPtrInst *GEP = GetElementPtrInst::Create(V, ops);
133 EXPECT_FALSE(this->clone(GEP)->isInBounds());
134
135 GEP->setIsInBounds();
136 EXPECT_TRUE(this->clone(GEP)->isInBounds());
137 }
138
TEST_F(CloneInstruction,Exact)139 TEST_F(CloneInstruction, Exact) {
140 V = new Argument(Type::getInt32Ty(context));
141
142 BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
143 EXPECT_FALSE(this->clone(SDiv)->isExact());
144
145 SDiv->setIsExact(true);
146 EXPECT_TRUE(this->clone(SDiv)->isExact());
147 }
148
TEST_F(CloneInstruction,Attributes)149 TEST_F(CloneInstruction, Attributes) {
150 Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
151 FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
152
153 Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
154 BasicBlock *BB = BasicBlock::Create(context, "", F1);
155 IRBuilder<> Builder(BB);
156 Builder.CreateRetVoid();
157
158 Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
159
160 Attribute::AttrKind AK[] = { Attribute::NoCapture };
161 AttributeSet AS = AttributeSet::get(context, 0, AK);
162 Argument *A = F1->arg_begin();
163 A->addAttr(AS);
164
165 SmallVector<ReturnInst*, 4> Returns;
166 ValueToValueMapTy VMap;
167 VMap[A] = UndefValue::get(A->getType());
168
169 CloneFunctionInto(F2, F1, VMap, false, Returns);
170 EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());
171 }
172
173 }
174