blob: 1d22d5b15c9ba6125f6a7ab1d903d00e4f36c0ee [file] [log] [blame]
Nick Lewycky1f715782009-09-27 21:39:46 +00001//===- 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
Alon Mishne07d949f2014-03-12 14:42:51 +000010#include "llvm/Transforms/Utils/Cloning.h"
11#include "llvm/ADT/ArrayRef.h"
Chandler Carruth130cec22012-12-04 10:23:08 +000012#include "llvm/ADT/STLExtras.h"
Quentin Colombet4156c982014-04-22 02:17:11 +000013#include "llvm/ADT/SmallPtrSet.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000014#include "llvm/IR/Argument.h"
15#include "llvm/IR/Constant.h"
Alon Mishne07d949f2014-03-12 14:42:51 +000016#include "llvm/IR/DIBuilder.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000017#include "llvm/IR/DebugInfo.h"
Joey Gouly81259292013-04-10 10:37:38 +000018#include "llvm/IR/Function.h"
Joey Gouly81259292013-04-10 10:37:38 +000019#include "llvm/IR/IRBuilder.h"
Alon Mishne07d949f2014-03-12 14:42:51 +000020#include "llvm/IR/InstIterator.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000021#include "llvm/IR/Instructions.h"
Alon Mishne07d949f2014-03-12 14:42:51 +000022#include "llvm/IR/IntrinsicInst.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000023#include "llvm/IR/LLVMContext.h"
Chandler Carruthd9903882015-01-14 11:23:27 +000024#include "llvm/IR/Module.h"
Chandler Carruth130cec22012-12-04 10:23:08 +000025#include "gtest/gtest.h"
Nick Lewycky1f715782009-09-27 21:39:46 +000026
27using namespace llvm;
28
David Blaikiea379b1812011-12-20 02:50:00 +000029namespace {
Chandler Carruth35e67062012-06-20 08:39:27 +000030
Nick Lewycky84189ab2010-03-13 19:58:26 +000031class CloneInstruction : public ::testing::Test {
32protected:
33 virtual void SetUp() {
Craig Topper66f09ad2014-06-08 22:29:17 +000034 V = nullptr;
Nick Lewycky84189ab2010-03-13 19:58:26 +000035 }
36
37 template <typename T>
38 T *clone(T *V1) {
39 Value *V2 = V1->clone();
Quentin Colombet4156c982014-04-22 02:17:11 +000040 Orig.insert(V1);
41 Clones.insert(V2);
Nick Lewycky84189ab2010-03-13 19:58:26 +000042 return cast<T>(V2);
43 }
44
Quentin Colombet4156c982014-04-22 02:17:11 +000045 void eraseClones() {
46 DeleteContainerPointers(Clones);
47 }
Nick Lewycky84189ab2010-03-13 19:58:26 +000048
49 virtual void TearDown() {
50 eraseClones();
Quentin Colombet4156c982014-04-22 02:17:11 +000051 DeleteContainerPointers(Orig);
52 delete V;
Nick Lewycky84189ab2010-03-13 19:58:26 +000053 }
54
Quentin Colombet4156c982014-04-22 02:17:11 +000055 SmallPtrSet<Value *, 4> Orig; // Erase on exit
56 SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones
Nick Lewycky84189ab2010-03-13 19:58:26 +000057
Nick Lewycky1f715782009-09-27 21:39:46 +000058 LLVMContext context;
Quentin Colombet4156c982014-04-22 02:17:11 +000059 Value *V;
Nick Lewycky84189ab2010-03-13 19:58:26 +000060};
61
62TEST_F(CloneInstruction, OverflowBits) {
Quentin Colombet4156c982014-04-22 02:17:11 +000063 V = new Argument(Type::getInt32Ty(context));
Nick Lewycky1f715782009-09-27 21:39:46 +000064
Quentin Colombet4156c982014-04-22 02:17:11 +000065 BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V);
66 BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V);
67 BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V);
Nick Lewycky1f715782009-09-27 21:39:46 +000068
Nick Lewycky84189ab2010-03-13 19:58:26 +000069 BinaryOperator *AddClone = this->clone(Add);
70 BinaryOperator *SubClone = this->clone(Sub);
71 BinaryOperator *MulClone = this->clone(Mul);
72
73 EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
74 EXPECT_FALSE(AddClone->hasNoSignedWrap());
75 EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
76 EXPECT_FALSE(SubClone->hasNoSignedWrap());
77 EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
78 EXPECT_FALSE(MulClone->hasNoSignedWrap());
79
80 eraseClones();
Nick Lewycky1f715782009-09-27 21:39:46 +000081
82 Add->setHasNoUnsignedWrap();
83 Sub->setHasNoUnsignedWrap();
84 Mul->setHasNoUnsignedWrap();
85
Nick Lewycky84189ab2010-03-13 19:58:26 +000086 AddClone = this->clone(Add);
87 SubClone = this->clone(Sub);
88 MulClone = this->clone(Mul);
89
90 EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
91 EXPECT_FALSE(AddClone->hasNoSignedWrap());
92 EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
93 EXPECT_FALSE(SubClone->hasNoSignedWrap());
94 EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
95 EXPECT_FALSE(MulClone->hasNoSignedWrap());
96
97 eraseClones();
Nick Lewycky1f715782009-09-27 21:39:46 +000098
99 Add->setHasNoSignedWrap();
100 Sub->setHasNoSignedWrap();
101 Mul->setHasNoSignedWrap();
102
Nick Lewycky84189ab2010-03-13 19:58:26 +0000103 AddClone = this->clone(Add);
104 SubClone = this->clone(Sub);
105 MulClone = this->clone(Mul);
106
107 EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
108 EXPECT_TRUE(AddClone->hasNoSignedWrap());
109 EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
110 EXPECT_TRUE(SubClone->hasNoSignedWrap());
111 EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
112 EXPECT_TRUE(MulClone->hasNoSignedWrap());
113
114 eraseClones();
Nick Lewycky1f715782009-09-27 21:39:46 +0000115
116 Add->setHasNoUnsignedWrap(false);
117 Sub->setHasNoUnsignedWrap(false);
118 Mul->setHasNoUnsignedWrap(false);
119
Nick Lewycky84189ab2010-03-13 19:58:26 +0000120 AddClone = this->clone(Add);
121 SubClone = this->clone(Sub);
122 MulClone = this->clone(Mul);
123
124 EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
125 EXPECT_TRUE(AddClone->hasNoSignedWrap());
126 EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
127 EXPECT_TRUE(SubClone->hasNoSignedWrap());
128 EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
129 EXPECT_TRUE(MulClone->hasNoSignedWrap());
Nick Lewycky1f715782009-09-27 21:39:46 +0000130}
131
Nick Lewycky84189ab2010-03-13 19:58:26 +0000132TEST_F(CloneInstruction, Inbounds) {
Quentin Colombet4156c982014-04-22 02:17:11 +0000133 V = new Argument(Type::getInt32PtrTy(context));
Nick Lewycky84189ab2010-03-13 19:58:26 +0000134
Nick Lewycky1f715782009-09-27 21:39:46 +0000135 Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
136 std::vector<Value *> ops;
137 ops.push_back(Z);
Quentin Colombet4156c982014-04-22 02:17:11 +0000138 GetElementPtrInst *GEP = GetElementPtrInst::Create(V, ops);
Nick Lewycky84189ab2010-03-13 19:58:26 +0000139 EXPECT_FALSE(this->clone(GEP)->isInBounds());
Nick Lewycky1f715782009-09-27 21:39:46 +0000140
141 GEP->setIsInBounds();
Nick Lewycky84189ab2010-03-13 19:58:26 +0000142 EXPECT_TRUE(this->clone(GEP)->isInBounds());
Nick Lewycky1f715782009-09-27 21:39:46 +0000143}
144
Nick Lewycky84189ab2010-03-13 19:58:26 +0000145TEST_F(CloneInstruction, Exact) {
Quentin Colombet4156c982014-04-22 02:17:11 +0000146 V = new Argument(Type::getInt32Ty(context));
Nick Lewycky1f715782009-09-27 21:39:46 +0000147
Quentin Colombet4156c982014-04-22 02:17:11 +0000148 BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
Nick Lewycky84189ab2010-03-13 19:58:26 +0000149 EXPECT_FALSE(this->clone(SDiv)->isExact());
Nick Lewycky1f715782009-09-27 21:39:46 +0000150
151 SDiv->setIsExact(true);
Nick Lewycky84189ab2010-03-13 19:58:26 +0000152 EXPECT_TRUE(this->clone(SDiv)->isExact());
Nick Lewycky1f715782009-09-27 21:39:46 +0000153}
Chandler Carruth35e67062012-06-20 08:39:27 +0000154
Joey Gouly81259292013-04-10 10:37:38 +0000155TEST_F(CloneInstruction, Attributes) {
156 Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
157 FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
158
159 Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
160 BasicBlock *BB = BasicBlock::Create(context, "", F1);
161 IRBuilder<> Builder(BB);
162 Builder.CreateRetVoid();
163
164 Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
165
166 Attribute::AttrKind AK[] = { Attribute::NoCapture };
167 AttributeSet AS = AttributeSet::get(context, 0, AK);
168 Argument *A = F1->arg_begin();
169 A->addAttr(AS);
170
171 SmallVector<ReturnInst*, 4> Returns;
172 ValueToValueMapTy VMap;
173 VMap[A] = UndefValue::get(A->getType());
174
175 CloneFunctionInto(F2, F1, VMap, false, Returns);
176 EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());
Joey Gouly51f6fb92013-04-10 23:21:26 +0000177
178 delete F1;
179 delete F2;
Joey Gouly81259292013-04-10 10:37:38 +0000180}
181
Reid Kleckner23798a92014-03-26 22:26:35 +0000182TEST_F(CloneInstruction, CallingConvention) {
183 Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
184 FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
185
186 Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
187 F1->setCallingConv(CallingConv::Cold);
188 BasicBlock *BB = BasicBlock::Create(context, "", F1);
189 IRBuilder<> Builder(BB);
190 Builder.CreateRetVoid();
191
192 Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
193
194 SmallVector<ReturnInst*, 4> Returns;
195 ValueToValueMapTy VMap;
196 VMap[F1->arg_begin()] = F2->arg_begin();
197
198 CloneFunctionInto(F2, F1, VMap, false, Returns);
199 EXPECT_EQ(CallingConv::Cold, F2->getCallingConv());
200
201 delete F1;
202 delete F2;
203}
204
Alon Mishne07d949f2014-03-12 14:42:51 +0000205class CloneFunc : public ::testing::Test {
206protected:
207 virtual void SetUp() {
208 SetupModule();
209 CreateOldFunc();
210 CreateNewFunc();
211 SetupFinder();
212 }
213
214 virtual void TearDown() {
215 delete Finder;
216 }
217
218 void SetupModule() {
219 M = new Module("", C);
220 }
221
222 void CreateOldFunc() {
223 FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false);
224 OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M);
225 CreateOldFunctionBodyAndDI();
226 }
227
228 void CreateOldFunctionBodyAndDI() {
229 DIBuilder DBuilder(*M);
230 IRBuilder<> IBuilder(C);
231
232 // Function DI
233 DIFile File = DBuilder.createFile("filename.c", "/file/dir/");
Manman Renf8a19672014-07-28 22:24:06 +0000234 DITypeArray ParamTypes = DBuilder.getOrCreateTypeArray(None);
Alon Mishne07d949f2014-03-12 14:42:51 +0000235 DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes);
236 DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99,
237 "filename.c", "/file/dir", "CloneFunc", false, "", 0);
238
239 DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4,
240 FuncType, true, true, 3, 0, false, OldFunc);
241
242 // Function body
243 BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc);
244 IBuilder.SetInsertPoint(Entry);
245 DebugLoc Loc = DebugLoc::get(3, 2, Subprogram);
246 IBuilder.SetCurrentDebugLocation(Loc);
247 AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C));
248 IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram));
249 Value* AllocaContent = IBuilder.getInt32(1);
250 Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca);
251 IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram));
252 Instruction* Terminator = IBuilder.CreateRetVoid();
253
254 // Create a local variable around the alloca
255 DIType IntType = DBuilder.createBasicType("int", 32, 0,
256 dwarf::DW_ATE_signed);
Adrian Prantl87b7eb92014-10-01 18:55:02 +0000257 DIExpression E = DBuilder.createExpression();
Alon Mishne07d949f2014-03-12 14:42:51 +0000258 DIVariable Variable = DBuilder.createLocalVariable(
259 dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true);
Adrian Prantl87b7eb92014-10-01 18:55:02 +0000260 DBuilder.insertDeclare(Alloca, Variable, E, Store);
261 DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, Terminator);
Alon Mishne07d949f2014-03-12 14:42:51 +0000262 // 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
273 void CreateNewFunc() {
274 ValueToValueMapTy VMap;
Craig Topper66f09ad2014-06-08 22:29:17 +0000275 NewFunc = CloneFunction(OldFunc, VMap, true, nullptr);
Alon Mishne07d949f2014-03-12 14:42:51 +0000276 M->getFunctionList().push_back(NewFunc);
277 }
278
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.
292TEST_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.
298TEST_F(CloneFunc, Subprogram) {
299 unsigned SubprogramCount = Finder->subprogram_count();
Justin Bognerf404b932014-03-12 17:00:52 +0000300 EXPECT_EQ(2U, SubprogramCount);
Alon Mishne07d949f2014-03-12 14:42:51 +0000301
Alon Mishnead312152014-03-18 09:41:07 +0000302 auto Iter = Finder->subprograms().begin();
Alon Mishne07d949f2014-03-12 14:42:51 +0000303 DISubprogram Sub1(*Iter);
304 EXPECT_TRUE(Sub1.Verify());
305 Iter++;
306 DISubprogram Sub2(*Iter);
307 EXPECT_TRUE(Sub2.Verify());
308
Eli Bendersky09a95e02014-03-12 16:14:53 +0000309 EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc)
310 || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc));
Alon Mishne07d949f2014-03-12 14:42:51 +0000311}
312
313// Test that the new subprogram entry was not added to the CU which doesn't
314// contain the old subprogram entry.
315TEST_F(CloneFunc, SubprogramInRightCU) {
Justin Bognerf404b932014-03-12 17:00:52 +0000316 EXPECT_EQ(2U, Finder->compile_unit_count());
Alon Mishne07d949f2014-03-12 14:42:51 +0000317
Alon Mishnead312152014-03-18 09:41:07 +0000318 auto Iter = Finder->compile_units().begin();
Alon Mishne07d949f2014-03-12 14:42:51 +0000319 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.
330TEST_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
367TEST_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
Chandler Carruth35e67062012-06-20 08:39:27 +0000409}