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/Transforms/Utils/Cloning.h"
11 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/SmallPtrSet.h"
14 #include "llvm/IR/Argument.h"
15 #include "llvm/IR/Constant.h"
16 #include "llvm/IR/DebugInfo.h"
17 #include "llvm/IR/DIBuilder.h"
18 #include "llvm/IR/Function.h"
19 #include "llvm/IR/IRBuilder.h"
20 #include "llvm/IR/InstIterator.h"
21 #include "llvm/IR/Instructions.h"
22 #include "llvm/IR/IntrinsicInst.h"
23 #include "llvm/IR/IRBuilder.h"
24 #include "llvm/IR/Module.h"
25 #include "llvm/IR/LLVMContext.h"
26 #include "gtest/gtest.h"
27
28 using namespace llvm;
29
30 namespace {
31
32 class CloneInstruction : public ::testing::Test {
33 protected:
SetUp()34 virtual void SetUp() {
35 V = nullptr;
36 }
37
38 template <typename T>
clone(T * V1)39 T *clone(T *V1) {
40 Value *V2 = V1->clone();
41 Orig.insert(V1);
42 Clones.insert(V2);
43 return cast<T>(V2);
44 }
45
eraseClones()46 void eraseClones() {
47 DeleteContainerPointers(Clones);
48 }
49
TearDown()50 virtual void TearDown() {
51 eraseClones();
52 DeleteContainerPointers(Orig);
53 delete V;
54 }
55
56 SmallPtrSet<Value *, 4> Orig; // Erase on exit
57 SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones
58
59 LLVMContext context;
60 Value *V;
61 };
62
TEST_F(CloneInstruction,OverflowBits)63 TEST_F(CloneInstruction, OverflowBits) {
64 V = new Argument(Type::getInt32Ty(context));
65
66 BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V);
67 BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V);
68 BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V);
69
70 BinaryOperator *AddClone = this->clone(Add);
71 BinaryOperator *SubClone = this->clone(Sub);
72 BinaryOperator *MulClone = this->clone(Mul);
73
74 EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
75 EXPECT_FALSE(AddClone->hasNoSignedWrap());
76 EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
77 EXPECT_FALSE(SubClone->hasNoSignedWrap());
78 EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
79 EXPECT_FALSE(MulClone->hasNoSignedWrap());
80
81 eraseClones();
82
83 Add->setHasNoUnsignedWrap();
84 Sub->setHasNoUnsignedWrap();
85 Mul->setHasNoUnsignedWrap();
86
87 AddClone = this->clone(Add);
88 SubClone = this->clone(Sub);
89 MulClone = this->clone(Mul);
90
91 EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
92 EXPECT_FALSE(AddClone->hasNoSignedWrap());
93 EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
94 EXPECT_FALSE(SubClone->hasNoSignedWrap());
95 EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
96 EXPECT_FALSE(MulClone->hasNoSignedWrap());
97
98 eraseClones();
99
100 Add->setHasNoSignedWrap();
101 Sub->setHasNoSignedWrap();
102 Mul->setHasNoSignedWrap();
103
104 AddClone = this->clone(Add);
105 SubClone = this->clone(Sub);
106 MulClone = this->clone(Mul);
107
108 EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
109 EXPECT_TRUE(AddClone->hasNoSignedWrap());
110 EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
111 EXPECT_TRUE(SubClone->hasNoSignedWrap());
112 EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
113 EXPECT_TRUE(MulClone->hasNoSignedWrap());
114
115 eraseClones();
116
117 Add->setHasNoUnsignedWrap(false);
118 Sub->setHasNoUnsignedWrap(false);
119 Mul->setHasNoUnsignedWrap(false);
120
121 AddClone = this->clone(Add);
122 SubClone = this->clone(Sub);
123 MulClone = this->clone(Mul);
124
125 EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
126 EXPECT_TRUE(AddClone->hasNoSignedWrap());
127 EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
128 EXPECT_TRUE(SubClone->hasNoSignedWrap());
129 EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
130 EXPECT_TRUE(MulClone->hasNoSignedWrap());
131 }
132
TEST_F(CloneInstruction,Inbounds)133 TEST_F(CloneInstruction, Inbounds) {
134 V = new Argument(Type::getInt32PtrTy(context));
135
136 Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
137 std::vector<Value *> ops;
138 ops.push_back(Z);
139 GetElementPtrInst *GEP = GetElementPtrInst::Create(V, ops);
140 EXPECT_FALSE(this->clone(GEP)->isInBounds());
141
142 GEP->setIsInBounds();
143 EXPECT_TRUE(this->clone(GEP)->isInBounds());
144 }
145
TEST_F(CloneInstruction,Exact)146 TEST_F(CloneInstruction, Exact) {
147 V = new Argument(Type::getInt32Ty(context));
148
149 BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
150 EXPECT_FALSE(this->clone(SDiv)->isExact());
151
152 SDiv->setIsExact(true);
153 EXPECT_TRUE(this->clone(SDiv)->isExact());
154 }
155
TEST_F(CloneInstruction,Attributes)156 TEST_F(CloneInstruction, Attributes) {
157 Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
158 FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
159
160 Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
161 BasicBlock *BB = BasicBlock::Create(context, "", F1);
162 IRBuilder<> Builder(BB);
163 Builder.CreateRetVoid();
164
165 Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
166
167 Attribute::AttrKind AK[] = { Attribute::NoCapture };
168 AttributeSet AS = AttributeSet::get(context, 0, AK);
169 Argument *A = F1->arg_begin();
170 A->addAttr(AS);
171
172 SmallVector<ReturnInst*, 4> Returns;
173 ValueToValueMapTy VMap;
174 VMap[A] = UndefValue::get(A->getType());
175
176 CloneFunctionInto(F2, F1, VMap, false, Returns);
177 EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());
178
179 delete F1;
180 delete F2;
181 }
182
TEST_F(CloneInstruction,CallingConvention)183 TEST_F(CloneInstruction, CallingConvention) {
184 Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
185 FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
186
187 Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
188 F1->setCallingConv(CallingConv::Cold);
189 BasicBlock *BB = BasicBlock::Create(context, "", F1);
190 IRBuilder<> Builder(BB);
191 Builder.CreateRetVoid();
192
193 Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
194
195 SmallVector<ReturnInst*, 4> Returns;
196 ValueToValueMapTy VMap;
197 VMap[F1->arg_begin()] = F2->arg_begin();
198
199 CloneFunctionInto(F2, F1, VMap, false, Returns);
200 EXPECT_EQ(CallingConv::Cold, F2->getCallingConv());
201
202 delete F1;
203 delete F2;
204 }
205
206 class CloneFunc : public ::testing::Test {
207 protected:
SetUp()208 virtual void SetUp() {
209 SetupModule();
210 CreateOldFunc();
211 CreateNewFunc();
212 SetupFinder();
213 }
214
TearDown()215 virtual void TearDown() {
216 delete Finder;
217 }
218
SetupModule()219 void SetupModule() {
220 M = new Module("", C);
221 }
222
CreateOldFunc()223 void CreateOldFunc() {
224 FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false);
225 OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M);
226 CreateOldFunctionBodyAndDI();
227 }
228
CreateOldFunctionBodyAndDI()229 void CreateOldFunctionBodyAndDI() {
230 DIBuilder DBuilder(*M);
231 IRBuilder<> IBuilder(C);
232
233 // Function DI
234 DIFile File = DBuilder.createFile("filename.c", "/file/dir/");
235 DIArray ParamTypes = DBuilder.getOrCreateArray(ArrayRef<Value*>());
236 DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes);
237 DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99,
238 "filename.c", "/file/dir", "CloneFunc", false, "", 0);
239
240 DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4,
241 FuncType, true, true, 3, 0, false, OldFunc);
242
243 // Function body
244 BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc);
245 IBuilder.SetInsertPoint(Entry);
246 DebugLoc Loc = DebugLoc::get(3, 2, Subprogram);
247 IBuilder.SetCurrentDebugLocation(Loc);
248 AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C));
249 IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram));
250 Value* AllocaContent = IBuilder.getInt32(1);
251 Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca);
252 IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram));
253 Instruction* Terminator = IBuilder.CreateRetVoid();
254
255 // Create a local variable around the alloca
256 DIType IntType = DBuilder.createBasicType("int", 32, 0,
257 dwarf::DW_ATE_signed);
258 DIVariable Variable = DBuilder.createLocalVariable(
259 dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true);
260 DBuilder.insertDeclare(Alloca, Variable, Store);
261 DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, Terminator);
262 // Finalize the debug info
263 DBuilder.finalize();
264
265
266 // Create another, empty, compile unit
267 DIBuilder DBuilder2(*M);
268 DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
269 "extra.c", "/file/dir", "CloneFunc", false, "", 0);
270 DBuilder2.finalize();
271 }
272
CreateNewFunc()273 void CreateNewFunc() {
274 ValueToValueMapTy VMap;
275 NewFunc = CloneFunction(OldFunc, VMap, true, nullptr);
276 M->getFunctionList().push_back(NewFunc);
277 }
278
SetupFinder()279 void SetupFinder() {
280 Finder = new DebugInfoFinder();
281 Finder->processModule(*M);
282 }
283
284 LLVMContext C;
285 Function* OldFunc;
286 Function* NewFunc;
287 Module* M;
288 DebugInfoFinder* Finder;
289 };
290
291 // Test that a new, distinct function was created.
TEST_F(CloneFunc,NewFunctionCreated)292 TEST_F(CloneFunc, NewFunctionCreated) {
293 EXPECT_NE(OldFunc, NewFunc);
294 }
295
296 // Test that a new subprogram entry was added and is pointing to the new
297 // function, while the original subprogram still points to the old one.
TEST_F(CloneFunc,Subprogram)298 TEST_F(CloneFunc, Subprogram) {
299 unsigned SubprogramCount = Finder->subprogram_count();
300 EXPECT_EQ(2U, SubprogramCount);
301
302 auto Iter = Finder->subprograms().begin();
303 DISubprogram Sub1(*Iter);
304 EXPECT_TRUE(Sub1.Verify());
305 Iter++;
306 DISubprogram Sub2(*Iter);
307 EXPECT_TRUE(Sub2.Verify());
308
309 EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc)
310 || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc));
311 }
312
313 // Test that the new subprogram entry was not added to the CU which doesn't
314 // contain the old subprogram entry.
TEST_F(CloneFunc,SubprogramInRightCU)315 TEST_F(CloneFunc, SubprogramInRightCU) {
316 EXPECT_EQ(2U, Finder->compile_unit_count());
317
318 auto Iter = Finder->compile_units().begin();
319 DICompileUnit CU1(*Iter);
320 EXPECT_TRUE(CU1.Verify());
321 Iter++;
322 DICompileUnit CU2(*Iter);
323 EXPECT_TRUE(CU2.Verify());
324 EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0
325 || CU2.getSubprograms().getNumElements() == 0);
326 }
327
328 // Test that instructions in the old function still belong to it in the
329 // metadata, while instruction in the new function belong to the new one.
TEST_F(CloneFunc,InstructionOwnership)330 TEST_F(CloneFunc, InstructionOwnership) {
331 inst_iterator OldIter = inst_begin(OldFunc);
332 inst_iterator OldEnd = inst_end(OldFunc);
333 inst_iterator NewIter = inst_begin(NewFunc);
334 inst_iterator NewEnd = inst_end(NewFunc);
335 while (OldIter != OldEnd && NewIter != NewEnd) {
336 Instruction& OldI = *OldIter;
337 Instruction& NewI = *NewIter;
338 EXPECT_NE(&OldI, &NewI);
339
340 EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
341 if (OldI.hasMetadata()) {
342 const DebugLoc& OldDL = OldI.getDebugLoc();
343 const DebugLoc& NewDL = NewI.getDebugLoc();
344
345 // Verify that the debug location data is the same
346 EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
347 EXPECT_EQ(OldDL.getCol(), NewDL.getCol());
348
349 // But that they belong to different functions
350 DISubprogram OldSubprogram(OldDL.getScope(C));
351 DISubprogram NewSubprogram(NewDL.getScope(C));
352 EXPECT_TRUE(OldSubprogram.Verify());
353 EXPECT_TRUE(NewSubprogram.Verify());
354 EXPECT_EQ(OldFunc, OldSubprogram.getFunction());
355 EXPECT_EQ(NewFunc, NewSubprogram.getFunction());
356 }
357
358 ++OldIter;
359 ++NewIter;
360 }
361 EXPECT_EQ(OldEnd, OldIter);
362 EXPECT_EQ(NewEnd, NewIter);
363 }
364
365 // Test that the arguments for debug intrinsics in the new function were
366 // properly cloned
TEST_F(CloneFunc,DebugIntrinsics)367 TEST_F(CloneFunc, DebugIntrinsics) {
368 inst_iterator OldIter = inst_begin(OldFunc);
369 inst_iterator OldEnd = inst_end(OldFunc);
370 inst_iterator NewIter = inst_begin(NewFunc);
371 inst_iterator NewEnd = inst_end(NewFunc);
372 while (OldIter != OldEnd && NewIter != NewEnd) {
373 Instruction& OldI = *OldIter;
374 Instruction& NewI = *NewIter;
375 if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
376 DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
377 EXPECT_TRUE(NewIntrin);
378
379 // Old address must belong to the old function
380 EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
381 getParent()->getParent());
382 // New address must belong to the new function
383 EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
384 getParent()->getParent());
385
386 // Old variable must belong to the old function
387 EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
388 .getContext()).getFunction());
389 // New variable must belong to the New function
390 EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
391 .getContext()).getFunction());
392 } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
393 DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
394 EXPECT_TRUE(NewIntrin);
395
396 // Old variable must belong to the old function
397 EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
398 .getContext()).getFunction());
399 // New variable must belong to the New function
400 EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
401 .getContext()).getFunction());
402 }
403
404 ++OldIter;
405 ++NewIter;
406 }
407 }
408
409 }
410