]>
git.proxmox.com Git - rustc.git/blob - src/llvm/unittests/Transforms/Utils/Cloning.cpp
1 //===- Cloning.cpp - Unit tests for the Cloner ----------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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/DIBuilder.h"
17 #include "llvm/IR/DebugInfo.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/LLVMContext.h"
24 #include "llvm/IR/Module.h"
25 #include "gtest/gtest.h"
31 class CloneInstruction
: public ::testing::Test
{
33 virtual void SetUp() {
39 Value
*V2
= V1
->clone();
46 DeleteContainerPointers(Clones
);
49 virtual void TearDown() {
51 DeleteContainerPointers(Orig
);
55 SmallPtrSet
<Value
*, 4> Orig
; // Erase on exit
56 SmallPtrSet
<Value
*, 4> Clones
; // Erase in eraseClones
62 TEST_F(CloneInstruction
, OverflowBits
) {
63 V
= new Argument(Type::getInt32Ty(context
));
65 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
);
69 BinaryOperator
*AddClone
= this->clone(Add
);
70 BinaryOperator
*SubClone
= this->clone(Sub
);
71 BinaryOperator
*MulClone
= this->clone(Mul
);
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());
82 Add
->setHasNoUnsignedWrap();
83 Sub
->setHasNoUnsignedWrap();
84 Mul
->setHasNoUnsignedWrap();
86 AddClone
= this->clone(Add
);
87 SubClone
= this->clone(Sub
);
88 MulClone
= this->clone(Mul
);
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());
99 Add
->setHasNoSignedWrap();
100 Sub
->setHasNoSignedWrap();
101 Mul
->setHasNoSignedWrap();
103 AddClone
= this->clone(Add
);
104 SubClone
= this->clone(Sub
);
105 MulClone
= this->clone(Mul
);
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());
116 Add
->setHasNoUnsignedWrap(false);
117 Sub
->setHasNoUnsignedWrap(false);
118 Mul
->setHasNoUnsignedWrap(false);
120 AddClone
= this->clone(Add
);
121 SubClone
= this->clone(Sub
);
122 MulClone
= this->clone(Mul
);
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());
132 TEST_F(CloneInstruction
, Inbounds
) {
133 V
= new Argument(Type::getInt32PtrTy(context
));
135 Constant
*Z
= Constant::getNullValue(Type::getInt32Ty(context
));
136 std::vector
<Value
*> ops
;
138 GetElementPtrInst
*GEP
= GetElementPtrInst::Create(V
, ops
);
139 EXPECT_FALSE(this->clone(GEP
)->isInBounds());
141 GEP
->setIsInBounds();
142 EXPECT_TRUE(this->clone(GEP
)->isInBounds());
145 TEST_F(CloneInstruction
, Exact
) {
146 V
= new Argument(Type::getInt32Ty(context
));
148 BinaryOperator
*SDiv
= BinaryOperator::Create(Instruction::SDiv
, V
, V
);
149 EXPECT_FALSE(this->clone(SDiv
)->isExact());
151 SDiv
->setIsExact(true);
152 EXPECT_TRUE(this->clone(SDiv
)->isExact());
155 TEST_F(CloneInstruction
, Attributes
) {
156 Type
*ArgTy1
[] = { Type::getInt32PtrTy(context
) };
157 FunctionType
*FT1
= FunctionType::get(Type::getVoidTy(context
), ArgTy1
, false);
159 Function
*F1
= Function::Create(FT1
, Function::ExternalLinkage
);
160 BasicBlock
*BB
= BasicBlock::Create(context
, "", F1
);
161 IRBuilder
<> Builder(BB
);
162 Builder
.CreateRetVoid();
164 Function
*F2
= Function::Create(FT1
, Function::ExternalLinkage
);
166 Attribute::AttrKind AK
[] = { Attribute::NoCapture
};
167 AttributeSet AS
= AttributeSet::get(context
, 0, AK
);
168 Argument
*A
= F1
->arg_begin();
171 SmallVector
<ReturnInst
*, 4> Returns
;
172 ValueToValueMapTy VMap
;
173 VMap
[A
] = UndefValue::get(A
->getType());
175 CloneFunctionInto(F2
, F1
, VMap
, false, Returns
);
176 EXPECT_FALSE(F2
->arg_begin()->hasNoCaptureAttr());
182 TEST_F(CloneInstruction
, CallingConvention
) {
183 Type
*ArgTy1
[] = { Type::getInt32PtrTy(context
) };
184 FunctionType
*FT1
= FunctionType::get(Type::getVoidTy(context
), ArgTy1
, false);
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();
192 Function
*F2
= Function::Create(FT1
, Function::ExternalLinkage
);
194 SmallVector
<ReturnInst
*, 4> Returns
;
195 ValueToValueMapTy VMap
;
196 VMap
[F1
->arg_begin()] = F2
->arg_begin();
198 CloneFunctionInto(F2
, F1
, VMap
, false, Returns
);
199 EXPECT_EQ(CallingConv::Cold
, F2
->getCallingConv());
205 class CloneFunc
: public ::testing::Test
{
207 virtual void SetUp() {
214 virtual void TearDown() {
219 M
= new Module("", C
);
222 void CreateOldFunc() {
223 FunctionType
* FuncType
= FunctionType::get(Type::getVoidTy(C
), false);
224 OldFunc
= Function::Create(FuncType
, GlobalValue::PrivateLinkage
, "f", M
);
225 CreateOldFunctionBodyAndDI();
228 void CreateOldFunctionBodyAndDI() {
229 DIBuilder
DBuilder(*M
);
230 IRBuilder
<> IBuilder(C
);
233 DIFile File
= DBuilder
.createFile("filename.c", "/file/dir/");
234 DITypeArray ParamTypes
= DBuilder
.getOrCreateTypeArray(None
);
235 DICompositeType FuncType
= DBuilder
.createSubroutineType(File
, ParamTypes
);
236 DICompileUnit CU
= DBuilder
.createCompileUnit(dwarf::DW_LANG_C99
,
237 "filename.c", "/file/dir", "CloneFunc", false, "", 0);
239 DISubprogram Subprogram
= DBuilder
.createFunction(CU
, "f", "f", File
, 4,
240 FuncType
, true, true, 3, 0, false, OldFunc
);
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();
254 // Create a local variable around the alloca
255 DIType IntType
= DBuilder
.createBasicType("int", 32, 0,
256 dwarf::DW_ATE_signed
);
257 DIExpression E
= DBuilder
.createExpression();
258 DIVariable Variable
= DBuilder
.createLocalVariable(
259 dwarf::DW_TAG_auto_variable
, Subprogram
, "x", File
, 5, IntType
, true);
260 DBuilder
.insertDeclare(Alloca
, Variable
, E
, Store
);
261 DBuilder
.insertDbgValueIntrinsic(AllocaContent
, 0, Variable
, E
, Terminator
);
262 // Finalize the debug info
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();
273 void CreateNewFunc() {
274 ValueToValueMapTy VMap
;
275 NewFunc
= CloneFunction(OldFunc
, VMap
, true, nullptr);
276 M
->getFunctionList().push_back(NewFunc
);
280 Finder
= new DebugInfoFinder();
281 Finder
->processModule(*M
);
288 DebugInfoFinder
* Finder
;
291 // Test that a new, distinct function was created.
292 TEST_F(CloneFunc
, NewFunctionCreated
) {
293 EXPECT_NE(OldFunc
, NewFunc
);
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.
298 TEST_F(CloneFunc
, Subprogram
) {
299 unsigned SubprogramCount
= Finder
->subprogram_count();
300 EXPECT_EQ(2U, SubprogramCount
);
302 auto Iter
= Finder
->subprograms().begin();
303 DISubprogram
Sub1(*Iter
);
304 EXPECT_TRUE(Sub1
.Verify());
306 DISubprogram
Sub2(*Iter
);
307 EXPECT_TRUE(Sub2
.Verify());
309 EXPECT_TRUE((Sub1
.getFunction() == OldFunc
&& Sub2
.getFunction() == NewFunc
)
310 || (Sub1
.getFunction() == NewFunc
&& Sub2
.getFunction() == OldFunc
));
313 // Test that the new subprogram entry was not added to the CU which doesn't
314 // contain the old subprogram entry.
315 TEST_F(CloneFunc
, SubprogramInRightCU
) {
316 EXPECT_EQ(2U, Finder
->compile_unit_count());
318 auto Iter
= Finder
->compile_units().begin();
319 DICompileUnit
CU1(*Iter
);
320 EXPECT_TRUE(CU1
.Verify());
322 DICompileUnit
CU2(*Iter
);
323 EXPECT_TRUE(CU2
.Verify());
324 EXPECT_TRUE(CU1
.getSubprograms().getNumElements() == 0
325 || CU2
.getSubprograms().getNumElements() == 0);
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.
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
);
340 EXPECT_EQ(OldI
.hasMetadata(), NewI
.hasMetadata());
341 if (OldI
.hasMetadata()) {
342 const DebugLoc
& OldDL
= OldI
.getDebugLoc();
343 const DebugLoc
& NewDL
= NewI
.getDebugLoc();
345 // Verify that the debug location data is the same
346 EXPECT_EQ(OldDL
.getLine(), NewDL
.getLine());
347 EXPECT_EQ(OldDL
.getCol(), NewDL
.getCol());
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());
361 EXPECT_EQ(OldEnd
, OldIter
);
362 EXPECT_EQ(NewEnd
, NewIter
);
365 // Test that the arguments for debug intrinsics in the new function were
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
);
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());
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
);
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());