blob: db1edd9c6d4767841740361945be7a98c21565c7 [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"
13#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/DebugInfo.h"
17#include "llvm/IR/DIBuilder.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"
23#include "llvm/IR/IRBuilder.h"
24#include "llvm/IR/Module.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000025#include "llvm/IR/LLVMContext.h"
Chandler Carruth130cec22012-12-04 10:23:08 +000026#include "gtest/gtest.h"
Nick Lewycky1f715782009-09-27 21:39:46 +000027
28using namespace llvm;
29
David Blaikiea379b1812011-12-20 02:50:00 +000030namespace {
Chandler Carruth35e67062012-06-20 08:39:27 +000031
Nick Lewycky84189ab2010-03-13 19:58:26 +000032class CloneInstruction : public ::testing::Test {
33protected:
34 virtual void SetUp() {
35 V = NULL;
36 }
37
38 template <typename T>
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
46 void eraseClones() {
47 DeleteContainerPointers(Clones);
48 }
49
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
Nick Lewycky1f715782009-09-27 21:39:46 +000059 LLVMContext context;
Nick Lewycky84189ab2010-03-13 19:58:26 +000060 Value *V;
61};
62
63TEST_F(CloneInstruction, OverflowBits) {
64 V = new Argument(Type::getInt32Ty(context));
Nick Lewycky1f715782009-09-27 21:39:46 +000065
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
Nick Lewycky84189ab2010-03-13 19:58:26 +000070 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();
Nick Lewycky1f715782009-09-27 21:39:46 +000082
83 Add->setHasNoUnsignedWrap();
84 Sub->setHasNoUnsignedWrap();
85 Mul->setHasNoUnsignedWrap();
86
Nick Lewycky84189ab2010-03-13 19:58:26 +000087 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();
Nick Lewycky1f715782009-09-27 21:39:46 +000099
100 Add->setHasNoSignedWrap();
101 Sub->setHasNoSignedWrap();
102 Mul->setHasNoSignedWrap();
103
Nick Lewycky84189ab2010-03-13 19:58:26 +0000104 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();
Nick Lewycky1f715782009-09-27 21:39:46 +0000116
117 Add->setHasNoUnsignedWrap(false);
118 Sub->setHasNoUnsignedWrap(false);
119 Mul->setHasNoUnsignedWrap(false);
120
Nick Lewycky84189ab2010-03-13 19:58:26 +0000121 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());
Nick Lewycky1f715782009-09-27 21:39:46 +0000131}
132
Nick Lewycky84189ab2010-03-13 19:58:26 +0000133TEST_F(CloneInstruction, Inbounds) {
134 V = new Argument(Type::getInt32PtrTy(context));
135
Nick Lewycky1f715782009-09-27 21:39:46 +0000136 Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
137 std::vector<Value *> ops;
138 ops.push_back(Z);
Jay Foadd1b78492011-07-25 09:48:08 +0000139 GetElementPtrInst *GEP = GetElementPtrInst::Create(V, ops);
Nick Lewycky84189ab2010-03-13 19:58:26 +0000140 EXPECT_FALSE(this->clone(GEP)->isInBounds());
Nick Lewycky1f715782009-09-27 21:39:46 +0000141
142 GEP->setIsInBounds();
Nick Lewycky84189ab2010-03-13 19:58:26 +0000143 EXPECT_TRUE(this->clone(GEP)->isInBounds());
Nick Lewycky1f715782009-09-27 21:39:46 +0000144}
145
Nick Lewycky84189ab2010-03-13 19:58:26 +0000146TEST_F(CloneInstruction, Exact) {
147 V = new Argument(Type::getInt32Ty(context));
Nick Lewycky1f715782009-09-27 21:39:46 +0000148
149 BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
Nick Lewycky84189ab2010-03-13 19:58:26 +0000150 EXPECT_FALSE(this->clone(SDiv)->isExact());
Nick Lewycky1f715782009-09-27 21:39:46 +0000151
152 SDiv->setIsExact(true);
Nick Lewycky84189ab2010-03-13 19:58:26 +0000153 EXPECT_TRUE(this->clone(SDiv)->isExact());
Nick Lewycky1f715782009-09-27 21:39:46 +0000154}
Chandler Carruth35e67062012-06-20 08:39:27 +0000155
Joey Gouly81259292013-04-10 10:37:38 +0000156TEST_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());
Joey Gouly51f6fb92013-04-10 23:21:26 +0000178
179 delete F1;
180 delete F2;
Joey Gouly81259292013-04-10 10:37:38 +0000181}
182
Alon Mishne07d949f2014-03-12 14:42:51 +0000183class CloneFunc : public ::testing::Test {
184protected:
185 virtual void SetUp() {
186 SetupModule();
187 CreateOldFunc();
188 CreateNewFunc();
189 SetupFinder();
190 }
191
192 virtual void TearDown() {
193 delete Finder;
194 }
195
196 void SetupModule() {
197 M = new Module("", C);
198 }
199
200 void CreateOldFunc() {
201 FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false);
202 OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M);
203 CreateOldFunctionBodyAndDI();
204 }
205
206 void CreateOldFunctionBodyAndDI() {
207 DIBuilder DBuilder(*M);
208 IRBuilder<> IBuilder(C);
209
210 // Function DI
211 DIFile File = DBuilder.createFile("filename.c", "/file/dir/");
212 DIArray ParamTypes = DBuilder.getOrCreateArray(ArrayRef<Value*>());
213 DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes);
214 DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99,
215 "filename.c", "/file/dir", "CloneFunc", false, "", 0);
216
217 DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4,
218 FuncType, true, true, 3, 0, false, OldFunc);
219
220 // Function body
221 BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc);
222 IBuilder.SetInsertPoint(Entry);
223 DebugLoc Loc = DebugLoc::get(3, 2, Subprogram);
224 IBuilder.SetCurrentDebugLocation(Loc);
225 AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C));
226 IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram));
227 Value* AllocaContent = IBuilder.getInt32(1);
228 Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca);
229 IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram));
230 Instruction* Terminator = IBuilder.CreateRetVoid();
231
232 // Create a local variable around the alloca
233 DIType IntType = DBuilder.createBasicType("int", 32, 0,
234 dwarf::DW_ATE_signed);
235 DIVariable Variable = DBuilder.createLocalVariable(
236 dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true);
237 DBuilder.insertDeclare(Alloca, Variable, Store);
238 DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, Terminator);
239 // Finalize the debug info
240 DBuilder.finalize();
241
242
243 // Create another, empty, compile unit
244 DIBuilder DBuilder2(*M);
245 DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
246 "extra.c", "/file/dir", "CloneFunc", false, "", 0);
247 DBuilder2.finalize();
248 }
249
250 void CreateNewFunc() {
251 ValueToValueMapTy VMap;
252 NewFunc = CloneFunction(OldFunc, VMap, true, NULL);
253 M->getFunctionList().push_back(NewFunc);
254 }
255
256 void SetupFinder() {
257 Finder = new DebugInfoFinder();
258 Finder->processModule(*M);
259 }
260
261 LLVMContext C;
262 Function* OldFunc;
263 Function* NewFunc;
264 Module* M;
265 DebugInfoFinder* Finder;
266};
267
268// Test that a new, distinct function was created.
269TEST_F(CloneFunc, NewFunctionCreated) {
270 EXPECT_NE(OldFunc, NewFunc);
271}
272
273// Test that a new subprogram entry was added and is pointing to the new
274// function, while the original subprogram still points to the old one.
275TEST_F(CloneFunc, Subprogram) {
276 unsigned SubprogramCount = Finder->subprogram_count();
277 EXPECT_EQ(2, SubprogramCount);
278
279 DebugInfoFinder::iterator Iter = Finder->subprogram_begin();
280 DISubprogram Sub1(*Iter);
281 EXPECT_TRUE(Sub1.Verify());
282 Iter++;
283 DISubprogram Sub2(*Iter);
284 EXPECT_TRUE(Sub2.Verify());
285
Eli Bendersky09a95e02014-03-12 16:14:53 +0000286 EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc)
287 || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc));
Alon Mishne07d949f2014-03-12 14:42:51 +0000288}
289
290// Test that the new subprogram entry was not added to the CU which doesn't
291// contain the old subprogram entry.
292TEST_F(CloneFunc, SubprogramInRightCU) {
293 EXPECT_EQ(2, Finder->compile_unit_count());
294
295 DebugInfoFinder::iterator Iter = Finder->compile_unit_begin();
296 DICompileUnit CU1(*Iter);
297 EXPECT_TRUE(CU1.Verify());
298 Iter++;
299 DICompileUnit CU2(*Iter);
300 EXPECT_TRUE(CU2.Verify());
301 EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0
302 || CU2.getSubprograms().getNumElements() == 0);
303}
304
305// Test that instructions in the old function still belong to it in the
306// metadata, while instruction in the new function belong to the new one.
307TEST_F(CloneFunc, InstructionOwnership) {
308 inst_iterator OldIter = inst_begin(OldFunc);
309 inst_iterator OldEnd = inst_end(OldFunc);
310 inst_iterator NewIter = inst_begin(NewFunc);
311 inst_iterator NewEnd = inst_end(NewFunc);
312 while (OldIter != OldEnd && NewIter != NewEnd) {
313 Instruction& OldI = *OldIter;
314 Instruction& NewI = *NewIter;
315 EXPECT_NE(&OldI, &NewI);
316
317 EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
318 if (OldI.hasMetadata()) {
319 const DebugLoc& OldDL = OldI.getDebugLoc();
320 const DebugLoc& NewDL = NewI.getDebugLoc();
321
322 // Verify that the debug location data is the same
323 EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
324 EXPECT_EQ(OldDL.getCol(), NewDL.getCol());
325
326 // But that they belong to different functions
327 DISubprogram OldSubprogram(OldDL.getScope(C));
328 DISubprogram NewSubprogram(NewDL.getScope(C));
329 EXPECT_TRUE(OldSubprogram.Verify());
330 EXPECT_TRUE(NewSubprogram.Verify());
331 EXPECT_EQ(OldFunc, OldSubprogram.getFunction());
332 EXPECT_EQ(NewFunc, NewSubprogram.getFunction());
333 }
334
335 ++OldIter;
336 ++NewIter;
337 }
338 EXPECT_EQ(OldEnd, OldIter);
339 EXPECT_EQ(NewEnd, NewIter);
340}
341
342// Test that the arguments for debug intrinsics in the new function were
343// properly cloned
344TEST_F(CloneFunc, DebugIntrinsics) {
345 inst_iterator OldIter = inst_begin(OldFunc);
346 inst_iterator OldEnd = inst_end(OldFunc);
347 inst_iterator NewIter = inst_begin(NewFunc);
348 inst_iterator NewEnd = inst_end(NewFunc);
349 while (OldIter != OldEnd && NewIter != NewEnd) {
350 Instruction& OldI = *OldIter;
351 Instruction& NewI = *NewIter;
352 if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
353 DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
354 EXPECT_TRUE(NewIntrin);
355
356 // Old address must belong to the old function
357 EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
358 getParent()->getParent());
359 // New address must belong to the new function
360 EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
361 getParent()->getParent());
362
363 // Old variable must belong to the old function
364 EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
365 .getContext()).getFunction());
366 // New variable must belong to the New function
367 EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
368 .getContext()).getFunction());
369 } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
370 DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
371 EXPECT_TRUE(NewIntrin);
372
373 // Old variable must belong to the old function
374 EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
375 .getContext()).getFunction());
376 // New variable must belong to the New function
377 EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
378 .getContext()).getFunction());
379 }
380
381 ++OldIter;
382 ++NewIter;
383 }
384}
385
Chandler Carruth35e67062012-06-20 08:39:27 +0000386}