aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Transforms/Utils/CloningTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/unittests/Transforms/Utils/CloningTest.cpp')
-rw-r--r--llvm/unittests/Transforms/Utils/CloningTest.cpp70
1 files changed, 61 insertions, 9 deletions
diff --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp
index 016e772..6bab802 100644
--- a/llvm/unittests/Transforms/Utils/CloningTest.cpp
+++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp
@@ -177,7 +177,8 @@ TEST_F(CloneInstruction, Attributes) {
ValueToValueMapTy VMap;
VMap[A] = UndefValue::get(A->getType());
- CloneFunctionInto(F2, F1, VMap, false, Returns);
+ CloneFunctionInto(F2, F1, VMap, CloneFunctionChangeType::LocalChangesOnly,
+ Returns);
EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());
delete F1;
@@ -200,7 +201,8 @@ TEST_F(CloneInstruction, CallingConvention) {
ValueToValueMapTy VMap;
VMap[&*F1->arg_begin()] = &*F2->arg_begin();
- CloneFunctionInto(F2, F1, VMap, false, Returns);
+ CloneFunctionInto(F2, F1, VMap, CloneFunctionChangeType::LocalChangesOnly,
+ Returns);
EXPECT_EQ(CallingConv::Cold, F2->getCallingConv());
delete F1;
@@ -663,6 +665,28 @@ static int GetDICompileUnitCount(const Module& M) {
return 0;
}
+static bool haveCompileUnitsInCommon(const Module &LHS, const Module &RHS) {
+ const NamedMDNode *LHSCUs = LHS.getNamedMetadata("llvm.dbg.cu");
+ if (!LHSCUs)
+ return false;
+
+ const NamedMDNode *RHSCUs = RHS.getNamedMetadata("llvm.dbg.cu");
+ if (!RHSCUs)
+ return false;
+
+ SmallPtrSet<const MDNode *, 8> Found;
+ for (int I = 0, E = LHSCUs->getNumOperands(); I != E; ++I)
+ if (const MDNode *N = LHSCUs->getOperand(I))
+ Found.insert(N);
+
+ for (int I = 0, E = RHSCUs->getNumOperands(); I != E; ++I)
+ if (const MDNode *N = RHSCUs->getOperand(I))
+ if (Found.count(N))
+ return true;
+
+ return false;
+}
+
TEST(CloneFunction, CloneEmptyFunction) {
StringRef ImplAssembly = R"(
define void @foo() {
@@ -684,7 +708,8 @@ TEST(CloneFunction, CloneEmptyFunction) {
ValueToValueMapTy VMap;
SmallVector<ReturnInst *, 8> Returns;
ClonedCodeInfo CCI;
- CloneFunctionInto(ImplFunction, DeclFunction, VMap, true, Returns, "", &CCI);
+ CloneFunctionInto(ImplFunction, DeclFunction, VMap,
+ CloneFunctionChangeType::GlobalChanges, Returns, "", &CCI);
EXPECT_FALSE(verifyModule(*ImplModule, &errs()));
EXPECT_FALSE(CCI.ContainsCalls);
@@ -715,7 +740,8 @@ TEST(CloneFunction, CloneFunctionWithInalloca) {
ValueToValueMapTy VMap;
SmallVector<ReturnInst *, 8> Returns;
ClonedCodeInfo CCI;
- CloneFunctionInto(DeclFunction, ImplFunction, VMap, true, Returns, "", &CCI);
+ CloneFunctionInto(DeclFunction, ImplFunction, VMap,
+ CloneFunctionChangeType::GlobalChanges, Returns, "", &CCI);
EXPECT_FALSE(verifyModule(*ImplModule, &errs()));
EXPECT_TRUE(CCI.ContainsCalls);
@@ -764,7 +790,8 @@ TEST(CloneFunction, CloneFunctionWithSubprograms) {
ValueToValueMapTy VMap;
SmallVector<ReturnInst *, 8> Returns;
ClonedCodeInfo CCI;
- CloneFunctionInto(NewFunc, OldFunc, VMap, true, Returns, "", &CCI);
+ CloneFunctionInto(NewFunc, OldFunc, VMap,
+ CloneFunctionChangeType::GlobalChanges, Returns, "", &CCI);
// This fails if the scopes in the llvm.dbg.declare variable and location
// aren't the same.
@@ -812,12 +839,14 @@ TEST(CloneFunction, CloneFunctionToDifferentModule) {
VMap[ImplFunction] = DeclFunction;
// No args to map
SmallVector<ReturnInst*, 8> Returns;
- CloneFunctionInto(DeclFunction, ImplFunction, VMap, true, Returns);
+ CloneFunctionInto(DeclFunction, ImplFunction, VMap,
+ CloneFunctionChangeType::DifferentModule, Returns);
EXPECT_FALSE(verifyModule(*ImplModule, &errs()));
EXPECT_FALSE(verifyModule(*DeclModule, &errs()));
- // DICompileUnit !2 shall be inserted into DeclModule.
+ // DICompileUnit !2 shall be cloned into DeclModule.
EXPECT_TRUE(GetDICompileUnitCount(*DeclModule) == 1);
+ EXPECT_FALSE(haveCompileUnitsInCommon(*ImplModule, *DeclModule));
}
class CloneModule : public ::testing::Test {
@@ -840,6 +869,16 @@ protected:
GV->addMetadata(LLVMContext::MD_type, *MDNode::get(C, {}));
GV->setComdat(CD);
+ {
+ // Add an empty compile unit first that isn't otherwise referenced, to
+ // confirm that compile units get cloned in the correct order.
+ DIBuilder EmptyBuilder(*OldM);
+ auto *File = EmptyBuilder.createFile("empty.c", "/file/dir/");
+ (void)EmptyBuilder.createCompileUnit(dwarf::DW_LANG_C99, File,
+ "EmptyUnit", false, "", 0);
+ EmptyBuilder.finalize();
+ }
+
DIBuilder DBuilder(*OldM);
IRBuilder<> IBuilder(C);
@@ -894,6 +933,10 @@ protected:
};
TEST_F(CloneModule, Verify) {
+ // Confirm the old module is (still) valid.
+ EXPECT_FALSE(verifyModule(*OldM));
+
+ // Check the new module.
EXPECT_FALSE(verifyModule(*NewM));
}
@@ -944,10 +987,19 @@ TEST_F(CloneModule, CompileUnit) {
// Find DICompileUnit listed in llvm.dbg.cu
auto *NMD = NewM->getNamedMetadata("llvm.dbg.cu");
EXPECT_TRUE(NMD != nullptr);
- EXPECT_EQ(NMD->getNumOperands(), 1U);
+ EXPECT_EQ(NMD->getNumOperands(), 2U);
+ EXPECT_FALSE(haveCompileUnitsInCommon(*OldM, *NewM));
+
+ // Check that the empty CU is first, even though it's not referenced except
+ // from named metadata.
+ DICompileUnit *EmptyCU = dyn_cast<llvm::DICompileUnit>(NMD->getOperand(0));
+ EXPECT_TRUE(EmptyCU != nullptr);
+ EXPECT_EQ("EmptyUnit", EmptyCU->getProducer());
- DICompileUnit *CU = dyn_cast<llvm::DICompileUnit>(NMD->getOperand(0));
+ // Get the interesting CU.
+ DICompileUnit *CU = dyn_cast<llvm::DICompileUnit>(NMD->getOperand(1));
EXPECT_TRUE(CU != nullptr);
+ EXPECT_EQ("CloneModule", CU->getProducer());
// Assert this CU is consistent with the cloned function debug info
DISubprogram *SP = NewM->getFunction("f")->getSubprogram();