Cloning.cpp revision 37ed9c199ca639565f6ce88105f9e39e898d82d0
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
28using namespace llvm;
29
30namespace {
31
32class CloneInstruction : public ::testing::Test {
33protected:
34  virtual void SetUp() {
35    V = nullptr;
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
59  LLVMContext context;
60  Value *V;
61};
62
63TEST_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
133TEST_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
146TEST_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
156TEST_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
183TEST_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
206class CloneFunc : public ::testing::Test {
207protected:
208  virtual void SetUp() {
209    SetupModule();
210    CreateOldFunc();
211    CreateNewFunc();
212    SetupFinder();
213  }
214
215  virtual void TearDown() {
216    delete Finder;
217  }
218
219  void SetupModule() {
220    M = new Module("", C);
221  }
222
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
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    DITypeArray ParamTypes = DBuilder.getOrCreateTypeArray(None);
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    DIExpression E = DBuilder.createExpression();
259    DIVariable Variable = DBuilder.createLocalVariable(
260      dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true);
261    DBuilder.insertDeclare(Alloca, Variable, E, Store);
262    DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, Terminator);
263    // Finalize the debug info
264    DBuilder.finalize();
265
266
267    // Create another, empty, compile unit
268    DIBuilder DBuilder2(*M);
269    DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
270        "extra.c", "/file/dir", "CloneFunc", false, "", 0);
271    DBuilder2.finalize();
272  }
273
274  void CreateNewFunc() {
275    ValueToValueMapTy VMap;
276    NewFunc = CloneFunction(OldFunc, VMap, true, nullptr);
277    M->getFunctionList().push_back(NewFunc);
278  }
279
280  void SetupFinder() {
281    Finder = new DebugInfoFinder();
282    Finder->processModule(*M);
283  }
284
285  LLVMContext C;
286  Function* OldFunc;
287  Function* NewFunc;
288  Module* M;
289  DebugInfoFinder* Finder;
290};
291
292// Test that a new, distinct function was created.
293TEST_F(CloneFunc, NewFunctionCreated) {
294  EXPECT_NE(OldFunc, NewFunc);
295}
296
297// Test that a new subprogram entry was added and is pointing to the new
298// function, while the original subprogram still points to the old one.
299TEST_F(CloneFunc, Subprogram) {
300  unsigned SubprogramCount = Finder->subprogram_count();
301  EXPECT_EQ(2U, SubprogramCount);
302
303  auto Iter = Finder->subprograms().begin();
304  DISubprogram Sub1(*Iter);
305  EXPECT_TRUE(Sub1.Verify());
306  Iter++;
307  DISubprogram Sub2(*Iter);
308  EXPECT_TRUE(Sub2.Verify());
309
310  EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc)
311           || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc));
312}
313
314// Test that the new subprogram entry was not added to the CU which doesn't
315// contain the old subprogram entry.
316TEST_F(CloneFunc, SubprogramInRightCU) {
317  EXPECT_EQ(2U, Finder->compile_unit_count());
318
319  auto Iter = Finder->compile_units().begin();
320  DICompileUnit CU1(*Iter);
321  EXPECT_TRUE(CU1.Verify());
322  Iter++;
323  DICompileUnit CU2(*Iter);
324  EXPECT_TRUE(CU2.Verify());
325  EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0
326           || CU2.getSubprograms().getNumElements() == 0);
327}
328
329// Test that instructions in the old function still belong to it in the
330// metadata, while instruction in the new function belong to the new one.
331TEST_F(CloneFunc, InstructionOwnership) {
332  inst_iterator OldIter = inst_begin(OldFunc);
333  inst_iterator OldEnd = inst_end(OldFunc);
334  inst_iterator NewIter = inst_begin(NewFunc);
335  inst_iterator NewEnd = inst_end(NewFunc);
336  while (OldIter != OldEnd && NewIter != NewEnd) {
337    Instruction& OldI = *OldIter;
338    Instruction& NewI = *NewIter;
339    EXPECT_NE(&OldI, &NewI);
340
341    EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
342    if (OldI.hasMetadata()) {
343      const DebugLoc& OldDL = OldI.getDebugLoc();
344      const DebugLoc& NewDL = NewI.getDebugLoc();
345
346      // Verify that the debug location data is the same
347      EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
348      EXPECT_EQ(OldDL.getCol(), NewDL.getCol());
349
350      // But that they belong to different functions
351      DISubprogram OldSubprogram(OldDL.getScope(C));
352      DISubprogram NewSubprogram(NewDL.getScope(C));
353      EXPECT_TRUE(OldSubprogram.Verify());
354      EXPECT_TRUE(NewSubprogram.Verify());
355      EXPECT_EQ(OldFunc, OldSubprogram.getFunction());
356      EXPECT_EQ(NewFunc, NewSubprogram.getFunction());
357    }
358
359    ++OldIter;
360    ++NewIter;
361  }
362  EXPECT_EQ(OldEnd, OldIter);
363  EXPECT_EQ(NewEnd, NewIter);
364}
365
366// Test that the arguments for debug intrinsics in the new function were
367// properly cloned
368TEST_F(CloneFunc, DebugIntrinsics) {
369  inst_iterator OldIter = inst_begin(OldFunc);
370  inst_iterator OldEnd = inst_end(OldFunc);
371  inst_iterator NewIter = inst_begin(NewFunc);
372  inst_iterator NewEnd = inst_end(NewFunc);
373  while (OldIter != OldEnd && NewIter != NewEnd) {
374    Instruction& OldI = *OldIter;
375    Instruction& NewI = *NewIter;
376    if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
377      DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
378      EXPECT_TRUE(NewIntrin);
379
380      // Old address must belong to the old function
381      EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
382                         getParent()->getParent());
383      // New address must belong to the new function
384      EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
385                         getParent()->getParent());
386
387      // Old variable must belong to the old function
388      EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
389                         .getContext()).getFunction());
390      // New variable must belong to the New function
391      EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
392                         .getContext()).getFunction());
393    } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
394      DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
395      EXPECT_TRUE(NewIntrin);
396
397      // Old variable must belong to the old function
398      EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable())
399                         .getContext()).getFunction());
400      // New variable must belong to the New function
401      EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable())
402                         .getContext()).getFunction());
403    }
404
405    ++OldIter;
406    ++NewIter;
407  }
408}
409
410}
411