1 //===- Cloning.cpp - Unit tests for the Cloner ----------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Transforms/Utils/Cloning.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/SmallPtrSet.h"
12 #include "llvm/Analysis/AliasAnalysis.h"
13 #include "llvm/Analysis/DomTreeUpdater.h"
14 #include "llvm/Analysis/LoopInfo.h"
15 #include "llvm/AsmParser/Parser.h"
16 #include "llvm/IR/Argument.h"
17 #include "llvm/IR/Constant.h"
18 #include "llvm/IR/DIBuilder.h"
19 #include "llvm/IR/DebugInfo.h"
20 #include "llvm/IR/Function.h"
21 #include "llvm/IR/IRBuilder.h"
22 #include "llvm/IR/InstIterator.h"
23 #include "llvm/IR/Instructions.h"
24 #include "llvm/IR/IntrinsicInst.h"
25 #include "llvm/IR/LLVMContext.h"
26 #include "llvm/IR/Module.h"
27 #include "llvm/IR/Verifier.h"
28 #include "llvm/Support/SourceMgr.h"
29 #include "gtest/gtest.h"
35 class CloneInstruction
: public ::testing::Test
{
37 void SetUp() override
{ V
= nullptr; }
41 Value
*V2
= V1
->clone();
48 for (Value
*V
: Clones
)
53 void TearDown() override
{
62 SmallPtrSet
<Value
*, 4> Orig
; // Erase on exit
63 SmallPtrSet
<Value
*, 4> Clones
; // Erase in eraseClones
69 TEST_F(CloneInstruction
, OverflowBits
) {
70 V
= new Argument(Type::getInt32Ty(context
));
72 BinaryOperator
*Add
= BinaryOperator::Create(Instruction::Add
, V
, V
);
73 BinaryOperator
*Sub
= BinaryOperator::Create(Instruction::Sub
, V
, V
);
74 BinaryOperator
*Mul
= BinaryOperator::Create(Instruction::Mul
, V
, V
);
76 BinaryOperator
*AddClone
= this->clone(Add
);
77 BinaryOperator
*SubClone
= this->clone(Sub
);
78 BinaryOperator
*MulClone
= this->clone(Mul
);
80 EXPECT_FALSE(AddClone
->hasNoUnsignedWrap());
81 EXPECT_FALSE(AddClone
->hasNoSignedWrap());
82 EXPECT_FALSE(SubClone
->hasNoUnsignedWrap());
83 EXPECT_FALSE(SubClone
->hasNoSignedWrap());
84 EXPECT_FALSE(MulClone
->hasNoUnsignedWrap());
85 EXPECT_FALSE(MulClone
->hasNoSignedWrap());
89 Add
->setHasNoUnsignedWrap();
90 Sub
->setHasNoUnsignedWrap();
91 Mul
->setHasNoUnsignedWrap();
93 AddClone
= this->clone(Add
);
94 SubClone
= this->clone(Sub
);
95 MulClone
= this->clone(Mul
);
97 EXPECT_TRUE(AddClone
->hasNoUnsignedWrap());
98 EXPECT_FALSE(AddClone
->hasNoSignedWrap());
99 EXPECT_TRUE(SubClone
->hasNoUnsignedWrap());
100 EXPECT_FALSE(SubClone
->hasNoSignedWrap());
101 EXPECT_TRUE(MulClone
->hasNoUnsignedWrap());
102 EXPECT_FALSE(MulClone
->hasNoSignedWrap());
106 Add
->setHasNoSignedWrap();
107 Sub
->setHasNoSignedWrap();
108 Mul
->setHasNoSignedWrap();
110 AddClone
= this->clone(Add
);
111 SubClone
= this->clone(Sub
);
112 MulClone
= this->clone(Mul
);
114 EXPECT_TRUE(AddClone
->hasNoUnsignedWrap());
115 EXPECT_TRUE(AddClone
->hasNoSignedWrap());
116 EXPECT_TRUE(SubClone
->hasNoUnsignedWrap());
117 EXPECT_TRUE(SubClone
->hasNoSignedWrap());
118 EXPECT_TRUE(MulClone
->hasNoUnsignedWrap());
119 EXPECT_TRUE(MulClone
->hasNoSignedWrap());
123 Add
->setHasNoUnsignedWrap(false);
124 Sub
->setHasNoUnsignedWrap(false);
125 Mul
->setHasNoUnsignedWrap(false);
127 AddClone
= this->clone(Add
);
128 SubClone
= this->clone(Sub
);
129 MulClone
= this->clone(Mul
);
131 EXPECT_FALSE(AddClone
->hasNoUnsignedWrap());
132 EXPECT_TRUE(AddClone
->hasNoSignedWrap());
133 EXPECT_FALSE(SubClone
->hasNoUnsignedWrap());
134 EXPECT_TRUE(SubClone
->hasNoSignedWrap());
135 EXPECT_FALSE(MulClone
->hasNoUnsignedWrap());
136 EXPECT_TRUE(MulClone
->hasNoSignedWrap());
139 TEST_F(CloneInstruction
, Inbounds
) {
140 V
= new Argument(PointerType::get(context
, 0));
142 Constant
*Z
= Constant::getNullValue(Type::getInt32Ty(context
));
143 std::vector
<Value
*> ops
;
145 GetElementPtrInst
*GEP
=
146 GetElementPtrInst::Create(Type::getInt32Ty(context
), V
, ops
);
147 EXPECT_FALSE(this->clone(GEP
)->isInBounds());
149 GEP
->setIsInBounds();
150 EXPECT_TRUE(this->clone(GEP
)->isInBounds());
153 TEST_F(CloneInstruction
, Exact
) {
154 V
= new Argument(Type::getInt32Ty(context
));
156 BinaryOperator
*SDiv
= BinaryOperator::Create(Instruction::SDiv
, V
, V
);
157 EXPECT_FALSE(this->clone(SDiv
)->isExact());
159 SDiv
->setIsExact(true);
160 EXPECT_TRUE(this->clone(SDiv
)->isExact());
163 TEST_F(CloneInstruction
, Attributes
) {
164 Type
*ArgTy1
[] = {PointerType::get(context
, 0)};
166 FunctionType::get(Type::getVoidTy(context
), ArgTy1
, false);
168 Function
*F1
= Function::Create(FT1
, Function::ExternalLinkage
);
169 BasicBlock
*BB
= BasicBlock::Create(context
, "", F1
);
170 IRBuilder
<> Builder(BB
);
171 Builder
.CreateRetVoid();
173 Function
*F2
= Function::Create(FT1
, Function::ExternalLinkage
);
175 Argument
*A
= &*F1
->arg_begin();
176 A
->addAttr(Attribute::NoCapture
);
178 SmallVector
<ReturnInst
*, 4> Returns
;
179 ValueToValueMapTy VMap
;
180 VMap
[A
] = UndefValue::get(A
->getType());
182 CloneFunctionInto(F2
, F1
, VMap
, CloneFunctionChangeType::LocalChangesOnly
,
184 EXPECT_FALSE(F2
->arg_begin()->hasNoCaptureAttr());
190 TEST_F(CloneInstruction
, CallingConvention
) {
191 Type
*ArgTy1
[] = {PointerType::get(context
, 0)};
193 FunctionType::get(Type::getVoidTy(context
), ArgTy1
, false);
195 Function
*F1
= Function::Create(FT1
, Function::ExternalLinkage
);
196 F1
->setCallingConv(CallingConv::Cold
);
197 BasicBlock
*BB
= BasicBlock::Create(context
, "", F1
);
198 IRBuilder
<> Builder(BB
);
199 Builder
.CreateRetVoid();
201 Function
*F2
= Function::Create(FT1
, Function::ExternalLinkage
);
203 SmallVector
<ReturnInst
*, 4> Returns
;
204 ValueToValueMapTy VMap
;
205 VMap
[&*F1
->arg_begin()] = &*F2
->arg_begin();
207 CloneFunctionInto(F2
, F1
, VMap
, CloneFunctionChangeType::LocalChangesOnly
,
209 EXPECT_EQ(CallingConv::Cold
, F2
->getCallingConv());
215 TEST_F(CloneInstruction
, DuplicateInstructionsToSplit
) {
216 Type
*ArgTy1
[] = {PointerType::get(context
, 0)};
217 FunctionType
*FT
= FunctionType::get(Type::getVoidTy(context
), ArgTy1
, false);
218 V
= new Argument(Type::getInt32Ty(context
));
220 Function
*F
= Function::Create(FT
, Function::ExternalLinkage
);
222 BasicBlock
*BB1
= BasicBlock::Create(context
, "", F
);
223 IRBuilder
<> Builder1(BB1
);
225 BasicBlock
*BB2
= BasicBlock::Create(context
, "", F
);
226 IRBuilder
<> Builder2(BB2
);
228 Builder1
.CreateBr(BB2
);
230 Instruction
*AddInst
= cast
<Instruction
>(Builder2
.CreateAdd(V
, V
));
231 Instruction
*MulInst
= cast
<Instruction
>(Builder2
.CreateMul(AddInst
, V
));
232 Instruction
*SubInst
= cast
<Instruction
>(Builder2
.CreateSub(MulInst
, V
));
233 Builder2
.CreateRetVoid();
236 ValueToValueMapTy Mapping
;
237 DomTreeUpdater
DTU(DomTreeUpdater::UpdateStrategy::Lazy
);
239 DuplicateInstructionsInSplitBetween(BB2
, BB1
, SubInst
, Mapping
, DTU
);
242 EXPECT_EQ(Mapping
.size(), 2u);
243 EXPECT_TRUE(Mapping
.find(AddInst
) != Mapping
.end());
244 EXPECT_TRUE(Mapping
.find(MulInst
) != Mapping
.end());
246 auto AddSplit
= dyn_cast
<Instruction
>(Mapping
[AddInst
]);
247 EXPECT_TRUE(AddSplit
);
248 EXPECT_EQ(AddSplit
->getOperand(0), V
);
249 EXPECT_EQ(AddSplit
->getOperand(1), V
);
250 EXPECT_EQ(AddSplit
->getParent(), Split
);
252 auto MulSplit
= dyn_cast
<Instruction
>(Mapping
[MulInst
]);
253 EXPECT_TRUE(MulSplit
);
254 EXPECT_EQ(MulSplit
->getOperand(0), AddSplit
);
255 EXPECT_EQ(MulSplit
->getOperand(1), V
);
256 EXPECT_EQ(MulSplit
->getParent(), Split
);
258 EXPECT_EQ(AddSplit
->getNextNode(), MulSplit
);
259 EXPECT_EQ(MulSplit
->getNextNode(), Split
->getTerminator());
264 TEST_F(CloneInstruction
, DuplicateInstructionsToSplitBlocksEq1
) {
265 Type
*ArgTy1
[] = {PointerType::get(context
, 0)};
266 FunctionType
*FT
= FunctionType::get(Type::getVoidTy(context
), ArgTy1
, false);
267 V
= new Argument(Type::getInt32Ty(context
));
269 Function
*F
= Function::Create(FT
, Function::ExternalLinkage
);
271 BasicBlock
*BB1
= BasicBlock::Create(context
, "", F
);
272 IRBuilder
<> Builder1(BB1
);
274 BasicBlock
*BB2
= BasicBlock::Create(context
, "", F
);
275 IRBuilder
<> Builder2(BB2
);
277 Builder1
.CreateBr(BB2
);
279 Instruction
*AddInst
= cast
<Instruction
>(Builder2
.CreateAdd(V
, V
));
280 Instruction
*MulInst
= cast
<Instruction
>(Builder2
.CreateMul(AddInst
, V
));
281 Instruction
*SubInst
= cast
<Instruction
>(Builder2
.CreateSub(MulInst
, V
));
282 Builder2
.CreateBr(BB2
);
285 DomTreeUpdater
DTU(DomTreeUpdater::UpdateStrategy::Lazy
);
286 ValueToValueMapTy Mapping
;
287 auto Split
= DuplicateInstructionsInSplitBetween(
288 BB2
, BB2
, BB2
->getTerminator(), Mapping
, DTU
);
291 EXPECT_EQ(Mapping
.size(), 3u);
292 EXPECT_TRUE(Mapping
.find(AddInst
) != Mapping
.end());
293 EXPECT_TRUE(Mapping
.find(MulInst
) != Mapping
.end());
294 EXPECT_TRUE(Mapping
.find(SubInst
) != Mapping
.end());
296 auto AddSplit
= dyn_cast
<Instruction
>(Mapping
[AddInst
]);
297 EXPECT_TRUE(AddSplit
);
298 EXPECT_EQ(AddSplit
->getOperand(0), V
);
299 EXPECT_EQ(AddSplit
->getOperand(1), V
);
300 EXPECT_EQ(AddSplit
->getParent(), Split
);
302 auto MulSplit
= dyn_cast
<Instruction
>(Mapping
[MulInst
]);
303 EXPECT_TRUE(MulSplit
);
304 EXPECT_EQ(MulSplit
->getOperand(0), AddSplit
);
305 EXPECT_EQ(MulSplit
->getOperand(1), V
);
306 EXPECT_EQ(MulSplit
->getParent(), Split
);
308 auto SubSplit
= dyn_cast
<Instruction
>(Mapping
[SubInst
]);
309 EXPECT_EQ(MulSplit
->getNextNode(), SubSplit
);
310 EXPECT_EQ(SubSplit
->getNextNode(), Split
->getTerminator());
311 EXPECT_EQ(Split
->getSingleSuccessor(), BB2
);
312 EXPECT_EQ(BB2
->getSingleSuccessor(), Split
);
317 TEST_F(CloneInstruction
, DuplicateInstructionsToSplitBlocksEq2
) {
318 Type
*ArgTy1
[] = {PointerType::get(context
, 0)};
319 FunctionType
*FT
= FunctionType::get(Type::getVoidTy(context
), ArgTy1
, false);
320 V
= new Argument(Type::getInt32Ty(context
));
322 Function
*F
= Function::Create(FT
, Function::ExternalLinkage
);
324 BasicBlock
*BB1
= BasicBlock::Create(context
, "", F
);
325 IRBuilder
<> Builder1(BB1
);
327 BasicBlock
*BB2
= BasicBlock::Create(context
, "", F
);
328 IRBuilder
<> Builder2(BB2
);
330 Builder1
.CreateBr(BB2
);
332 Instruction
*AddInst
= cast
<Instruction
>(Builder2
.CreateAdd(V
, V
));
333 Instruction
*MulInst
= cast
<Instruction
>(Builder2
.CreateMul(AddInst
, V
));
334 Instruction
*SubInst
= cast
<Instruction
>(Builder2
.CreateSub(MulInst
, V
));
335 Builder2
.CreateBr(BB2
);
338 DomTreeUpdater
DTU(DomTreeUpdater::UpdateStrategy::Lazy
);
339 ValueToValueMapTy Mapping
;
341 DuplicateInstructionsInSplitBetween(BB2
, BB2
, SubInst
, Mapping
, DTU
);
344 EXPECT_EQ(Mapping
.size(), 2u);
345 EXPECT_TRUE(Mapping
.find(AddInst
) != Mapping
.end());
346 EXPECT_TRUE(Mapping
.find(MulInst
) != Mapping
.end());
348 auto AddSplit
= dyn_cast
<Instruction
>(Mapping
[AddInst
]);
349 EXPECT_TRUE(AddSplit
);
350 EXPECT_EQ(AddSplit
->getOperand(0), V
);
351 EXPECT_EQ(AddSplit
->getOperand(1), V
);
352 EXPECT_EQ(AddSplit
->getParent(), Split
);
354 auto MulSplit
= dyn_cast
<Instruction
>(Mapping
[MulInst
]);
355 EXPECT_TRUE(MulSplit
);
356 EXPECT_EQ(MulSplit
->getOperand(0), AddSplit
);
357 EXPECT_EQ(MulSplit
->getOperand(1), V
);
358 EXPECT_EQ(MulSplit
->getParent(), Split
);
359 EXPECT_EQ(MulSplit
->getNextNode(), Split
->getTerminator());
360 EXPECT_EQ(Split
->getSingleSuccessor(), BB2
);
361 EXPECT_EQ(BB2
->getSingleSuccessor(), Split
);
366 static void runWithLoopInfoAndDominatorTree(
367 Module
&M
, StringRef FuncName
,
368 function_ref
<void(Function
&F
, LoopInfo
&LI
, DominatorTree
&DT
)> Test
) {
369 auto *F
= M
.getFunction(FuncName
);
370 ASSERT_NE(F
, nullptr) << "Could not find " << FuncName
;
372 DominatorTree
DT(*F
);
378 static std::unique_ptr
<Module
> parseIR(LLVMContext
&C
, const char *IR
) {
380 std::unique_ptr
<Module
> Mod
= parseAssemblyString(IR
, Err
, C
);
382 Err
.print("CloneLoop", errs());
386 TEST(CloneLoop
, CloneLoopNest
) {
390 std::unique_ptr
<Module
> M
= parseIR(
392 R
"(define void @foo(i32* %A, i32 %ub) {
394 %guardcmp = icmp slt i32 0, %ub
395 br i1 %guardcmp, label %for.outer.preheader, label %for.end
399 %j = phi i32 [ 0, %for.outer.preheader ], [ %inc.outer, %for.outer.latch ]
400 br i1 %guardcmp, label %for.inner.preheader, label %for.outer.latch
404 %i = phi i32 [ 0, %for.inner.preheader ], [ %inc, %for.inner ]
405 %idxprom = sext i32 %i to i64
406 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom
407 store i32 %i, i32* %arrayidx, align 4
408 %inc = add nsw i32 %i, 1
409 %cmp = icmp slt i32 %inc, %ub
410 br i1 %cmp, label %for.inner, label %for.inner.exit
412 br label %for.outer.latch
414 %inc.outer = add nsw i32 %j, 1
415 %cmp.outer = icmp slt i32 %inc.outer, %ub
416 br i1 %cmp.outer, label %for.outer, label %for.outer.exit
424 runWithLoopInfoAndDominatorTree(
425 *M
, "foo", [&](Function
&F
, LoopInfo
&LI
, DominatorTree
&DT
) {
426 Function::iterator FI
= F
.begin();
427 // First basic block is entry - skip it.
428 BasicBlock
*Preheader
= &*(++FI
);
429 BasicBlock
*Header
= &*(++FI
);
430 assert(Header
->getName() == "for.outer");
431 Loop
*L
= LI
.getLoopFor(Header
);
432 EXPECT_NE(L
, nullptr);
433 EXPECT_EQ(Header
, L
->getHeader());
434 EXPECT_EQ(Preheader
, L
->getLoopPreheader());
436 ValueToValueMapTy VMap
;
437 SmallVector
<BasicBlock
*, 4> ClonedLoopBlocks
;
438 Loop
*NewLoop
= cloneLoopWithPreheader(Preheader
, Preheader
, L
, VMap
,
439 "", &LI
, &DT
, ClonedLoopBlocks
);
440 EXPECT_NE(NewLoop
, nullptr);
441 EXPECT_EQ(NewLoop
->getSubLoops().size(), 1u);
442 Loop::block_iterator BI
= NewLoop
->block_begin();
443 EXPECT_TRUE((*BI
)->getName().startswith("for.outer"));
444 EXPECT_TRUE((*(++BI
))->getName().startswith("for.inner.preheader"));
445 EXPECT_TRUE((*(++BI
))->getName().startswith("for.inner"));
446 EXPECT_TRUE((*(++BI
))->getName().startswith("for.inner.exit"));
447 EXPECT_TRUE((*(++BI
))->getName().startswith("for.outer.latch"));
451 class CloneFunc
: public ::testing::Test
{
453 void SetUp() override
{
460 void TearDown() override
{ delete Finder
; }
463 M
= new Module("", C
);
466 void CreateOldFunc() {
467 FunctionType
* FuncType
= FunctionType::get(Type::getVoidTy(C
), false);
468 OldFunc
= Function::Create(FuncType
, GlobalValue::PrivateLinkage
, "f", M
);
469 CreateOldFunctionBodyAndDI();
472 void CreateOldFunctionBodyAndDI() {
473 DIBuilder
DBuilder(*M
);
474 IRBuilder
<> IBuilder(C
);
477 auto *File
= DBuilder
.createFile("filename.c", "/file/dir/");
478 DITypeRefArray ParamTypes
= DBuilder
.getOrCreateTypeArray(std::nullopt
);
479 DISubroutineType
*FuncType
=
480 DBuilder
.createSubroutineType(ParamTypes
);
481 auto *CU
= DBuilder
.createCompileUnit(dwarf::DW_LANG_C99
,
482 DBuilder
.createFile("filename.c",
484 "CloneFunc", false, "", 0);
486 auto *Subprogram
= DBuilder
.createFunction(
487 CU
, "f", "f", File
, 4, FuncType
, 3, DINode::FlagZero
,
488 DISubprogram::SPFlagLocalToUnit
| DISubprogram::SPFlagDefinition
);
489 OldFunc
->setSubprogram(Subprogram
);
492 BasicBlock
* Entry
= BasicBlock::Create(C
, "", OldFunc
);
493 IBuilder
.SetInsertPoint(Entry
);
494 DebugLoc Loc
= DILocation::get(Subprogram
->getContext(), 3, 2, Subprogram
);
495 IBuilder
.SetCurrentDebugLocation(Loc
);
496 AllocaInst
* Alloca
= IBuilder
.CreateAlloca(IntegerType::getInt32Ty(C
));
497 IBuilder
.SetCurrentDebugLocation(
498 DILocation::get(Subprogram
->getContext(), 4, 2, Subprogram
));
499 Value
* AllocaContent
= IBuilder
.getInt32(1);
500 Instruction
* Store
= IBuilder
.CreateStore(AllocaContent
, Alloca
);
501 IBuilder
.SetCurrentDebugLocation(
502 DILocation::get(Subprogram
->getContext(), 5, 2, Subprogram
));
504 // Create a local variable around the alloca
505 auto *IntType
= DBuilder
.createBasicType("int", 32, dwarf::DW_ATE_signed
);
506 auto *E
= DBuilder
.createExpression();
508 DBuilder
.createAutoVariable(Subprogram
, "x", File
, 5, IntType
, true);
509 auto *DL
= DILocation::get(Subprogram
->getContext(), 5, 0, Subprogram
);
510 DBuilder
.insertDeclare(Alloca
, Variable
, E
, DL
, Store
);
511 DBuilder
.insertDbgValueIntrinsic(AllocaContent
, Variable
, E
, DL
, Entry
);
512 // Also create an inlined variable.
513 // Create a distinct struct type that we should not duplicate during
515 auto *StructType
= DICompositeType::getDistinct(
516 C
, dwarf::DW_TAG_structure_type
, "some_struct", nullptr, 0, nullptr,
517 nullptr, 32, 32, 0, DINode::FlagZero
, nullptr, 0, nullptr, nullptr);
518 auto *InlinedSP
= DBuilder
.createFunction(
519 CU
, "inlined", "inlined", File
, 8, FuncType
, 9, DINode::FlagZero
,
520 DISubprogram::SPFlagLocalToUnit
| DISubprogram::SPFlagDefinition
);
522 DBuilder
.createAutoVariable(InlinedSP
, "inlined", File
, 5, StructType
, true);
523 auto *Scope
= DBuilder
.createLexicalBlock(
524 DBuilder
.createLexicalBlockFile(InlinedSP
, File
), File
, 1, 1);
525 auto InlinedDL
= DILocation::get(
526 Subprogram
->getContext(), 9, 4, Scope
,
527 DILocation::get(Subprogram
->getContext(), 5, 2, Subprogram
));
528 IBuilder
.SetCurrentDebugLocation(InlinedDL
);
529 DBuilder
.insertDeclare(Alloca
, InlinedVar
, E
, InlinedDL
, Store
);
530 IBuilder
.CreateStore(IBuilder
.getInt32(2), Alloca
);
531 // Finalize the debug info.
533 IBuilder
.CreateRetVoid();
535 // Create another, empty, compile unit.
536 DIBuilder
DBuilder2(*M
);
537 DBuilder2
.createCompileUnit(dwarf::DW_LANG_C99
,
538 DBuilder
.createFile("extra.c", "/file/dir"),
539 "CloneFunc", false, "", 0);
540 DBuilder2
.finalize();
543 void CreateNewFunc() {
544 ValueToValueMapTy VMap
;
545 NewFunc
= CloneFunction(OldFunc
, VMap
, nullptr);
549 Finder
= new DebugInfoFinder();
550 Finder
->processModule(*M
);
557 DebugInfoFinder
* Finder
;
560 // Test that a new, distinct function was created.
561 TEST_F(CloneFunc
, NewFunctionCreated
) {
562 EXPECT_NE(OldFunc
, NewFunc
);
565 // Test that a new subprogram entry was added and is pointing to the new
566 // function, while the original subprogram still points to the old one.
567 TEST_F(CloneFunc
, Subprogram
) {
568 EXPECT_FALSE(verifyModule(*M
, &errs()));
569 EXPECT_EQ(3U, Finder
->subprogram_count());
570 EXPECT_NE(NewFunc
->getSubprogram(), OldFunc
->getSubprogram());
573 // Test that instructions in the old function still belong to it in the
574 // metadata, while instruction in the new function belong to the new one.
575 TEST_F(CloneFunc
, InstructionOwnership
) {
576 EXPECT_FALSE(verifyModule(*M
));
578 inst_iterator OldIter
= inst_begin(OldFunc
);
579 inst_iterator OldEnd
= inst_end(OldFunc
);
580 inst_iterator NewIter
= inst_begin(NewFunc
);
581 inst_iterator NewEnd
= inst_end(NewFunc
);
582 while (OldIter
!= OldEnd
&& NewIter
!= NewEnd
) {
583 Instruction
& OldI
= *OldIter
;
584 Instruction
& NewI
= *NewIter
;
585 EXPECT_NE(&OldI
, &NewI
);
587 EXPECT_EQ(OldI
.hasMetadata(), NewI
.hasMetadata());
588 if (OldI
.hasMetadata()) {
589 const DebugLoc
& OldDL
= OldI
.getDebugLoc();
590 const DebugLoc
& NewDL
= NewI
.getDebugLoc();
592 // Verify that the debug location data is the same
593 EXPECT_EQ(OldDL
.getLine(), NewDL
.getLine());
594 EXPECT_EQ(OldDL
.getCol(), NewDL
.getCol());
596 // But that they belong to different functions
597 auto *OldSubprogram
= cast
<DISubprogram
>(OldDL
.getInlinedAtScope());
598 auto *NewSubprogram
= cast
<DISubprogram
>(NewDL
.getInlinedAtScope());
599 EXPECT_EQ(OldFunc
->getSubprogram(), OldSubprogram
);
600 EXPECT_EQ(NewFunc
->getSubprogram(), NewSubprogram
);
606 EXPECT_EQ(OldEnd
, OldIter
);
607 EXPECT_EQ(NewEnd
, NewIter
);
610 // Test that the arguments for debug intrinsics in the new function were
612 TEST_F(CloneFunc
, DebugIntrinsics
) {
613 EXPECT_FALSE(verifyModule(*M
));
615 inst_iterator OldIter
= inst_begin(OldFunc
);
616 inst_iterator OldEnd
= inst_end(OldFunc
);
617 inst_iterator NewIter
= inst_begin(NewFunc
);
618 inst_iterator NewEnd
= inst_end(NewFunc
);
619 while (OldIter
!= OldEnd
&& NewIter
!= NewEnd
) {
620 Instruction
& OldI
= *OldIter
;
621 Instruction
& NewI
= *NewIter
;
622 if (DbgDeclareInst
* OldIntrin
= dyn_cast
<DbgDeclareInst
>(&OldI
)) {
623 DbgDeclareInst
* NewIntrin
= dyn_cast
<DbgDeclareInst
>(&NewI
);
624 EXPECT_TRUE(NewIntrin
);
626 // Old address must belong to the old function
627 EXPECT_EQ(OldFunc
, cast
<AllocaInst
>(OldIntrin
->getAddress())->
628 getParent()->getParent());
629 // New address must belong to the new function
630 EXPECT_EQ(NewFunc
, cast
<AllocaInst
>(NewIntrin
->getAddress())->
631 getParent()->getParent());
633 if (OldIntrin
->getDebugLoc()->getInlinedAt()) {
634 // Inlined variable should refer to the same DILocalVariable as in the
636 EXPECT_EQ(OldIntrin
->getVariable(), NewIntrin
->getVariable());
638 // Old variable must belong to the old function.
639 EXPECT_EQ(OldFunc
->getSubprogram(),
640 cast
<DISubprogram
>(OldIntrin
->getVariable()->getScope()));
641 // New variable must belong to the new function.
642 EXPECT_EQ(NewFunc
->getSubprogram(),
643 cast
<DISubprogram
>(NewIntrin
->getVariable()->getScope()));
645 } else if (DbgValueInst
* OldIntrin
= dyn_cast
<DbgValueInst
>(&OldI
)) {
646 DbgValueInst
* NewIntrin
= dyn_cast
<DbgValueInst
>(&NewI
);
647 EXPECT_TRUE(NewIntrin
);
649 if (!OldIntrin
->getDebugLoc()->getInlinedAt()) {
650 // Old variable must belong to the old function.
651 EXPECT_EQ(OldFunc
->getSubprogram(),
652 cast
<DISubprogram
>(OldIntrin
->getVariable()->getScope()));
653 // New variable must belong to the new function.
654 EXPECT_EQ(NewFunc
->getSubprogram(),
655 cast
<DISubprogram
>(NewIntrin
->getVariable()->getScope()));
664 static int GetDICompileUnitCount(const Module
& M
) {
665 if (const auto* LLVM_DBG_CU
= M
.getNamedMetadata("llvm.dbg.cu")) {
666 return LLVM_DBG_CU
->getNumOperands();
671 static bool haveCompileUnitsInCommon(const Module
&LHS
, const Module
&RHS
) {
672 const NamedMDNode
*LHSCUs
= LHS
.getNamedMetadata("llvm.dbg.cu");
676 const NamedMDNode
*RHSCUs
= RHS
.getNamedMetadata("llvm.dbg.cu");
680 SmallPtrSet
<const MDNode
*, 8> Found
;
681 for (int I
= 0, E
= LHSCUs
->getNumOperands(); I
!= E
; ++I
)
682 if (const MDNode
*N
= LHSCUs
->getOperand(I
))
685 for (int I
= 0, E
= RHSCUs
->getNumOperands(); I
!= E
; ++I
)
686 if (const MDNode
*N
= RHSCUs
->getOperand(I
))
693 TEST(CloneFunction
, CloneEmptyFunction
) {
694 StringRef ImplAssembly
= R
"(
704 auto ImplModule
= parseAssemblyString(ImplAssembly
, Error
, Context
);
705 EXPECT_TRUE(ImplModule
!= nullptr);
706 auto *ImplFunction
= ImplModule
->getFunction("foo");
707 EXPECT_TRUE(ImplFunction
!= nullptr);
708 auto *DeclFunction
= ImplModule
->getFunction("bar");
709 EXPECT_TRUE(DeclFunction
!= nullptr);
711 ValueToValueMapTy VMap
;
712 SmallVector
<ReturnInst
*, 8> Returns
;
714 CloneFunctionInto(ImplFunction
, DeclFunction
, VMap
,
715 CloneFunctionChangeType::GlobalChanges
, Returns
, "", &CCI
);
717 EXPECT_FALSE(verifyModule(*ImplModule
, &errs()));
718 EXPECT_FALSE(CCI
.ContainsCalls
);
719 EXPECT_FALSE(CCI
.ContainsDynamicAllocas
);
722 TEST(CloneFunction
, CloneFunctionWithInalloca
) {
723 StringRef ImplAssembly
= R
"(
724 declare void @a(i32* inalloca(i32))
726 %a = alloca inalloca i32
727 call void @a(i32* inalloca(i32) %a)
736 auto ImplModule
= parseAssemblyString(ImplAssembly
, Error
, Context
);
737 EXPECT_TRUE(ImplModule
!= nullptr);
738 auto *ImplFunction
= ImplModule
->getFunction("foo");
739 EXPECT_TRUE(ImplFunction
!= nullptr);
740 auto *DeclFunction
= ImplModule
->getFunction("bar");
741 EXPECT_TRUE(DeclFunction
!= nullptr);
743 ValueToValueMapTy VMap
;
744 SmallVector
<ReturnInst
*, 8> Returns
;
746 CloneFunctionInto(DeclFunction
, ImplFunction
, VMap
,
747 CloneFunctionChangeType::GlobalChanges
, Returns
, "", &CCI
);
749 EXPECT_FALSE(verifyModule(*ImplModule
, &errs()));
750 EXPECT_TRUE(CCI
.ContainsCalls
);
751 EXPECT_TRUE(CCI
.ContainsDynamicAllocas
);
754 TEST(CloneFunction
, CloneFunctionWithSubprograms
) {
755 // Tests that the debug info is duplicated correctly when a DISubprogram
756 // happens to be one of the operands of the DISubprogram that is being cloned.
757 // In general, operands of "test" that are distinct should be duplicated,
758 // but in this case "my_operator" should not be duplicated. If it is
759 // duplicated, the metadata in the llvm.dbg.declare could end up with
760 // different duplicates.
761 StringRef ImplAssembly
= R
"(
762 declare void @llvm.dbg.declare(metadata, metadata, metadata)
764 define void @test() !dbg !5 {
765 call void @llvm.dbg.declare(metadata i8* undef, metadata !4, metadata !DIExpression()), !dbg !6
769 declare void @cloned()
772 !llvm.module.flags = !{!2}
773 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1)
774 !1 = !DIFile(filename: "test
.cpp
", directory: "")
775 !2 = !{i32 1, !"Debug Info Version
", i32 3}
776 !3 = distinct !DISubprogram(name: "my_operator
", scope: !1, unit: !0, retainedNodes: !{!4})
777 !4 = !DILocalVariable(name: "awaitables
", scope: !3)
778 !5 = distinct !DISubprogram(name: "test
", scope: !3, unit: !0)
779 !6 = !DILocation(line: 55, column: 15, scope: !3, inlinedAt: !7)
780 !7 = distinct !DILocation(line: 73, column: 14, scope: !5)
786 auto ImplModule
= parseAssemblyString(ImplAssembly
, Error
, Context
);
787 EXPECT_TRUE(ImplModule
!= nullptr);
788 auto *OldFunc
= ImplModule
->getFunction("test");
789 EXPECT_TRUE(OldFunc
!= nullptr);
790 auto *NewFunc
= ImplModule
->getFunction("cloned");
791 EXPECT_TRUE(NewFunc
!= nullptr);
793 ValueToValueMapTy VMap
;
794 SmallVector
<ReturnInst
*, 8> Returns
;
796 CloneFunctionInto(NewFunc
, OldFunc
, VMap
,
797 CloneFunctionChangeType::GlobalChanges
, Returns
, "", &CCI
);
799 // This fails if the scopes in the llvm.dbg.declare variable and location
801 EXPECT_FALSE(verifyModule(*ImplModule
, &errs()));
804 TEST(CloneFunction
, CloneFunctionWithInlinedSubprograms
) {
805 StringRef ImplAssembly
= R
"(
806 declare void @llvm.dbg.declare(metadata, metadata, metadata)
808 define void @test() !dbg !3 {
809 call void @llvm.dbg.declare(metadata i8* undef, metadata !5, metadata !DIExpression()), !dbg !7
813 declare void @cloned()
816 !llvm.module.flags = !{!2}
817 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1)
818 !1 = !DIFile(filename: "test
.cpp
", directory: "")
819 !2 = !{i32 1, !"Debug Info Version
", i32 3}
820 !3 = distinct !DISubprogram(name: "test
", scope: !0, unit: !0)
821 !4 = distinct !DISubprogram(name: "inlined
", scope: !0, unit: !0, retainedNodes: !{!5})
822 !5 = !DILocalVariable(name: "awaitables
", scope: !4)
823 !6 = distinct !DILexicalBlock(scope: !4, file: !1, line: 1)
824 !7 = !DILocation(line: 1, scope: !6, inlinedAt: !8)
825 !8 = !DILocation(line: 10, scope: !3)
831 auto ImplModule
= parseAssemblyString(ImplAssembly
, Error
, Context
);
832 EXPECT_TRUE(ImplModule
!= nullptr);
833 auto *Func
= ImplModule
->getFunction("test");
834 EXPECT_TRUE(Func
!= nullptr);
835 auto *ClonedFunc
= ImplModule
->getFunction("cloned");
836 EXPECT_TRUE(ClonedFunc
!= nullptr);
838 ValueToValueMapTy VMap
;
839 SmallVector
<ReturnInst
*, 8> Returns
;
841 CloneFunctionInto(ClonedFunc
, Func
, VMap
,
842 CloneFunctionChangeType::GlobalChanges
, Returns
, "", &CCI
);
844 EXPECT_FALSE(verifyModule(*ImplModule
, &errs()));
846 // Check that DILexicalBlock of inlined function was not cloned.
847 auto DbgDeclareI
= Func
->begin()->begin();
848 auto ClonedDbgDeclareI
= ClonedFunc
->begin()->begin();
849 const DebugLoc
&DbgLoc
= DbgDeclareI
->getDebugLoc();
850 const DebugLoc
&ClonedDbgLoc
= ClonedDbgDeclareI
->getDebugLoc();
851 EXPECT_NE(DbgLoc
.get(), ClonedDbgLoc
.get());
852 EXPECT_EQ(cast
<DILexicalBlock
>(DbgLoc
.getScope()),
853 cast
<DILexicalBlock
>(ClonedDbgLoc
.getScope()));
856 TEST(CloneFunction
, CloneFunctionToDifferentModule
) {
857 StringRef ImplAssembly
= R
"(
862 !llvm.module.flags = !{!0}
863 !llvm.dbg.cu = !{!2, !6}
864 !0 = !{i32 1, !"Debug Info Version
", i32 3}
865 !1 = distinct !DISubprogram(unit: !2)
866 !2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3)
867 !3 = !DIFile(filename: "foo
.c
", directory: "/tmp
")
868 !4 = distinct !DISubprogram(unit: !2)
869 !5 = !DILocation(line: 4, scope: !1)
870 !6 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3)
872 StringRef DeclAssembly
= R
"(
879 auto ImplModule
= parseAssemblyString(ImplAssembly
, Error
, Context
);
880 EXPECT_TRUE(ImplModule
!= nullptr);
881 // DICompileUnits: !2, !6. Only !2 is reachable from @foo().
882 EXPECT_TRUE(GetDICompileUnitCount(*ImplModule
) == 2);
883 auto* ImplFunction
= ImplModule
->getFunction("foo");
884 EXPECT_TRUE(ImplFunction
!= nullptr);
886 auto DeclModule
= parseAssemblyString(DeclAssembly
, Error
, Context
);
887 EXPECT_TRUE(DeclModule
!= nullptr);
888 // No DICompileUnits defined here.
889 EXPECT_TRUE(GetDICompileUnitCount(*DeclModule
) == 0);
890 auto* DeclFunction
= DeclModule
->getFunction("foo");
891 EXPECT_TRUE(DeclFunction
!= nullptr);
893 ValueToValueMapTy VMap
;
894 VMap
[ImplFunction
] = DeclFunction
;
896 SmallVector
<ReturnInst
*, 8> Returns
;
897 CloneFunctionInto(DeclFunction
, ImplFunction
, VMap
,
898 CloneFunctionChangeType::DifferentModule
, Returns
);
900 EXPECT_FALSE(verifyModule(*ImplModule
, &errs()));
901 EXPECT_FALSE(verifyModule(*DeclModule
, &errs()));
902 // DICompileUnit !2 shall be cloned into DeclModule.
903 EXPECT_TRUE(GetDICompileUnitCount(*DeclModule
) == 1);
904 EXPECT_FALSE(haveCompileUnitsInCommon(*ImplModule
, *DeclModule
));
907 class CloneModule
: public ::testing::Test
{
909 void SetUp() override
{
915 void SetupModule() { OldM
= new Module("", C
); }
917 void CreateOldModule() {
918 auto *CD
= OldM
->getOrInsertComdat("comdat");
919 CD
->setSelectionKind(Comdat::ExactMatch
);
921 auto GV
= new GlobalVariable(
922 *OldM
, Type::getInt32Ty(C
), false, GlobalValue::ExternalLinkage
,
923 ConstantInt::get(Type::getInt32Ty(C
), 1), "gv");
924 GV
->addMetadata(LLVMContext::MD_type
, *MDNode::get(C
, {}));
929 const unsigned AddrSpace
= 123;
930 auto *FuncPtrTy
= PointerType::get(C
, AddrSpace
);
931 auto *FuncTy
= FunctionType::get(FuncPtrTy
, false);
933 auto *ResolverF
= Function::Create(FuncTy
, GlobalValue::PrivateLinkage
,
934 AddrSpace
, "resolver", OldM
);
935 BasicBlock
*ResolverBody
= BasicBlock::Create(C
, "", ResolverF
);
936 ReturnInst::Create(C
, ConstantPointerNull::get(FuncPtrTy
), ResolverBody
);
938 GlobalIFunc
*GI
= GlobalIFunc::create(FuncTy
, AddrSpace
,
939 GlobalValue::LinkOnceODRLinkage
,
940 "an_ifunc", ResolverF
, OldM
);
941 GI
->setVisibility(GlobalValue::ProtectedVisibility
);
945 // Add an empty compile unit first that isn't otherwise referenced, to
946 // confirm that compile units get cloned in the correct order.
947 DIBuilder
EmptyBuilder(*OldM
);
948 auto *File
= EmptyBuilder
.createFile("empty.c", "/file/dir/");
949 (void)EmptyBuilder
.createCompileUnit(dwarf::DW_LANG_C99
, File
,
950 "EmptyUnit", false, "", 0);
951 EmptyBuilder
.finalize();
954 DIBuilder
DBuilder(*OldM
);
955 IRBuilder
<> IBuilder(C
);
957 auto *FuncType
= FunctionType::get(Type::getVoidTy(C
), false);
958 auto *PersFn
= Function::Create(FuncType
, GlobalValue::ExternalLinkage
,
961 Function::Create(FuncType
, GlobalValue::PrivateLinkage
, "f", OldM
);
962 F
->setPersonalityFn(PersFn
);
966 auto *File
= DBuilder
.createFile("filename.c", "/file/dir/");
967 DITypeRefArray ParamTypes
= DBuilder
.getOrCreateTypeArray(std::nullopt
);
968 DISubroutineType
*DFuncType
= DBuilder
.createSubroutineType(ParamTypes
);
969 auto *CU
= DBuilder
.createCompileUnit(dwarf::DW_LANG_C99
,
970 DBuilder
.createFile("filename.c",
972 "CloneModule", false, "", 0);
974 auto *Subprogram
= DBuilder
.createFunction(
975 CU
, "f", "f", File
, 4, DFuncType
, 3, DINode::FlagZero
,
976 DISubprogram::SPFlagLocalToUnit
| DISubprogram::SPFlagDefinition
);
977 F
->setSubprogram(Subprogram
);
979 // Create and assign DIGlobalVariableExpression to gv
980 auto GVExpression
= DBuilder
.createGlobalVariableExpression(
981 Subprogram
, "gv", "gv", File
, 1, DBuilder
.createNullPtrType(), false);
982 GV
->addDebugInfo(GVExpression
);
984 // DIGlobalVariableExpression not attached to any global variable
985 auto Expr
= DBuilder
.createExpression(
986 ArrayRef
<uint64_t>{dwarf::DW_OP_constu
, 42U, dwarf::DW_OP_stack_value
});
988 DBuilder
.createGlobalVariableExpression(
989 Subprogram
, "unattached", "unattached", File
, 1,
990 DBuilder
.createNullPtrType(), false, true, Expr
);
992 auto *Entry
= BasicBlock::Create(C
, "", F
);
993 IBuilder
.SetInsertPoint(Entry
);
994 IBuilder
.CreateRetVoid();
997 Function::Create(FuncType
, GlobalValue::ExternalLinkage
, "g", OldM
);
998 G
->addMetadata(LLVMContext::MD_type
, *MDNode::get(C
, {}));
1000 // Finalize the debug info
1001 DBuilder
.finalize();
1004 void CreateNewModule() { NewM
= llvm::CloneModule(*OldM
).release(); }
1011 TEST_F(CloneModule
, Verify
) {
1012 // Confirm the old module is (still) valid.
1013 EXPECT_FALSE(verifyModule(*OldM
, &errs()));
1015 // Check the new module.
1016 EXPECT_FALSE(verifyModule(*NewM
, &errs()));
1019 TEST_F(CloneModule
, OldModuleUnchanged
) {
1020 DebugInfoFinder Finder
;
1021 Finder
.processModule(*OldM
);
1022 EXPECT_EQ(1U, Finder
.subprogram_count());
1025 TEST_F(CloneModule
, Subprogram
) {
1026 Function
*NewF
= NewM
->getFunction("f");
1027 DISubprogram
*SP
= NewF
->getSubprogram();
1028 EXPECT_TRUE(SP
!= nullptr);
1029 EXPECT_EQ(SP
->getName(), "f");
1030 EXPECT_EQ(SP
->getFile()->getFilename(), "filename.c");
1031 EXPECT_EQ(SP
->getLine(), (unsigned)4);
1034 TEST_F(CloneModule
, FunctionDeclarationMetadata
) {
1035 Function
*NewF
= NewM
->getFunction("g");
1036 EXPECT_NE(nullptr, NewF
->getMetadata(LLVMContext::MD_type
));
1039 TEST_F(CloneModule
, GlobalMetadata
) {
1040 GlobalVariable
*NewGV
= NewM
->getGlobalVariable("gv");
1041 EXPECT_NE(nullptr, NewGV
->getMetadata(LLVMContext::MD_type
));
1044 TEST_F(CloneModule
, GlobalDebugInfo
) {
1045 GlobalVariable
*NewGV
= NewM
->getGlobalVariable("gv");
1046 EXPECT_TRUE(NewGV
!= nullptr);
1048 // Find debug info expression assigned to global
1049 SmallVector
<DIGlobalVariableExpression
*, 1> GVs
;
1050 NewGV
->getDebugInfo(GVs
);
1051 EXPECT_EQ(GVs
.size(), 1U);
1053 DIGlobalVariableExpression
*GVExpr
= GVs
[0];
1054 DIGlobalVariable
*GV
= GVExpr
->getVariable();
1055 EXPECT_TRUE(GV
!= nullptr);
1057 EXPECT_EQ(GV
->getName(), "gv");
1058 EXPECT_EQ(GV
->getLine(), 1U);
1060 // Assert that the scope of the debug info attached to
1061 // global variable matches the cloned function.
1062 DISubprogram
*SP
= NewM
->getFunction("f")->getSubprogram();
1063 EXPECT_TRUE(SP
!= nullptr);
1064 EXPECT_EQ(GV
->getScope(), SP
);
1067 TEST_F(CloneModule
, CompileUnit
) {
1068 // Find DICompileUnit listed in llvm.dbg.cu
1069 auto *NMD
= NewM
->getNamedMetadata("llvm.dbg.cu");
1070 EXPECT_TRUE(NMD
!= nullptr);
1071 EXPECT_EQ(NMD
->getNumOperands(), 2U);
1072 EXPECT_FALSE(haveCompileUnitsInCommon(*OldM
, *NewM
));
1074 // Check that the empty CU is first, even though it's not referenced except
1075 // from named metadata.
1076 DICompileUnit
*EmptyCU
= dyn_cast
<llvm::DICompileUnit
>(NMD
->getOperand(0));
1077 EXPECT_TRUE(EmptyCU
!= nullptr);
1078 EXPECT_EQ("EmptyUnit", EmptyCU
->getProducer());
1080 // Get the interesting CU.
1081 DICompileUnit
*CU
= dyn_cast
<llvm::DICompileUnit
>(NMD
->getOperand(1));
1082 EXPECT_TRUE(CU
!= nullptr);
1083 EXPECT_EQ("CloneModule", CU
->getProducer());
1085 // Assert this CU is consistent with the cloned function debug info
1086 DISubprogram
*SP
= NewM
->getFunction("f")->getSubprogram();
1087 EXPECT_TRUE(SP
!= nullptr);
1088 EXPECT_EQ(SP
->getUnit(), CU
);
1090 // Check globals listed in CU have the correct scope
1091 DIGlobalVariableExpressionArray GlobalArray
= CU
->getGlobalVariables();
1092 EXPECT_EQ(GlobalArray
.size(), 2U);
1093 for (DIGlobalVariableExpression
*GVExpr
: GlobalArray
) {
1094 DIGlobalVariable
*GV
= GVExpr
->getVariable();
1095 EXPECT_EQ(GV
->getScope(), SP
);
1099 TEST_F(CloneModule
, Comdat
) {
1100 GlobalVariable
*NewGV
= NewM
->getGlobalVariable("gv");
1101 auto *CD
= NewGV
->getComdat();
1102 ASSERT_NE(nullptr, CD
);
1103 EXPECT_EQ("comdat", CD
->getName());
1104 EXPECT_EQ(Comdat::ExactMatch
, CD
->getSelectionKind());
1106 Function
*NewF
= NewM
->getFunction("f");
1107 EXPECT_EQ(CD
, NewF
->getComdat());
1110 TEST_F(CloneModule
, IFunc
) {
1111 ASSERT_EQ(1u, NewM
->ifunc_size());
1113 const GlobalIFunc
&IFunc
= *NewM
->ifunc_begin();
1114 EXPECT_EQ("an_ifunc", IFunc
.getName());
1115 EXPECT_EQ(GlobalValue::LinkOnceODRLinkage
, IFunc
.getLinkage());
1116 EXPECT_EQ(GlobalValue::ProtectedVisibility
, IFunc
.getVisibility());
1117 EXPECT_EQ(123u, IFunc
.getAddressSpace());
1119 const Function
*Resolver
= IFunc
.getResolverFunction();
1120 ASSERT_NE(nullptr, Resolver
);
1121 EXPECT_EQ("resolver", Resolver
->getName());
1122 EXPECT_EQ(GlobalValue::PrivateLinkage
, Resolver
->getLinkage());