| From af289e04413504c3bdc252e08c3fe17bf7ea6dc8 Mon Sep 17 00:00:00 2001 |
| From: Peter Collingbourne <peter@pcc.me.uk> |
| Date: Wed, 30 Mar 2016 22:05:13 +0000 |
| Subject: [PATCH] Cloning: Reduce complexity of debug info cloning and fix |
| correctness issue. |
| |
| Commit r260791 contained an error in that it would introduce a cross-module |
| reference in the old module. It also introduced O(N^2) complexity in the |
| module cloner by requiring the entire module to be visited for each function. |
| Fix both of these problems by avoiding use of the CloneDebugInfoMetadata |
| function (which is only designed to do intra-module cloning) and cloning |
| function-attached metadata in the same way that we clone all other metadata. |
| |
| Differential Revision: http://reviews.llvm.org/D18583 |
| |
| git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@264935 91177308-0d34-0410-b5e6-96231b3b80d8 |
| |
| Alpine maintainer notes: |
| - Corresponds to llvm-D17165-D18583.patch in Julia. |
| |
| include/llvm/Transforms/Utils/Cloning.h | 5 ----- |
| lib/Transforms/Utils/CloneFunction.cpp | 13 +++++++++++-- |
| lib/Transforms/Utils/CloneModule.cpp | 1 - |
| unittests/Transforms/Utils/Cloning.cpp | 6 ++++++ |
| 4 files changed, 17 insertions(+), 8 deletions(-) |
| |
| diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h |
| index 0bae2bd..4f006f2 100644 |
| |
| |
| @@ -130,11 +130,6 @@ Function *CloneFunction(const Function *F, ValueToValueMapTy &VMap, |
| bool ModuleLevelChanges, |
| ClonedCodeInfo *CodeInfo = nullptr); |
| |
| -/// Clone the module-level debug info associated with OldFunc. The cloned data |
| -/// will point to NewFunc instead. |
| -void CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc, |
| - ValueToValueMapTy &VMap); |
| - |
| /// Clone OldFunc into NewFunc, transforming the old arguments into references |
| /// to VMap values. Note that if NewFunc already has basic blocks, the ones |
| /// cloned into it will be added to the end of the function. This function |
| diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp |
| index 05b0a17..8e1715a 100644 |
| |
| |
| @@ -119,6 +119,15 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, |
| .addAttributes(NewFunc->getContext(), AttributeSet::FunctionIndex, |
| OldAttrs.getFnAttributes())); |
| |
| + SmallVector<std::pair<unsigned, MDNode *>, 1> MDs; |
| + OldFunc->getAllMetadata(MDs); |
| + for (auto MD : MDs) |
| + NewFunc->setMetadata( |
| + MD.first, |
| + MapMetadata(MD.second, VMap, |
| + ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, |
| + TypeMapper, Materializer)); |
| + |
| // Loop over all of the basic blocks in the function, cloning them as |
| // appropriate. Note that we save BE this way in order to handle cloning of |
| // recursive functions into themselves. |
| @@ -187,8 +196,8 @@ static void AddOperand(DICompileUnit *CU, DISubprogramArray SPs, |
| |
| // Clone the module-level debug info associated with OldFunc. The cloned data |
| // will point to NewFunc instead. |
| -void llvm::CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc, |
| - ValueToValueMapTy &VMap) { |
| +static void CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc, |
| + ValueToValueMapTy &VMap) { |
| DebugInfoFinder Finder; |
| Finder.processModule(*OldFunc->getParent()); |
| |
| diff --git a/lib/Transforms/Utils/CloneModule.cpp b/lib/Transforms/Utils/CloneModule.cpp |
| index 494e275..929f51b 100644 |
| |
| |
| @@ -138,7 +138,6 @@ std::unique_ptr<Module> llvm::CloneModule( |
| VMap[&*J] = &*DestI++; |
| } |
| |
| - CloneDebugInfoMetadata(F, &*I, VMap); |
| SmallVector<ReturnInst*, 8> Returns; // Ignore returns cloned. |
| CloneFunctionInto(F, &*I, VMap, /*ModuleLevelChanges=*/true, Returns); |
| } |
| diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp |
| index b761e4e..f06a20f 100644 |
| |
| |
| @@ -464,6 +464,12 @@ TEST_F(CloneModule, Verify) { |
| EXPECT_FALSE(verifyModule(*NewM)); |
| } |
| |
| +TEST_F(CloneModule, OldModuleUnchanged) { |
| + DebugInfoFinder Finder; |
| + Finder.processModule(*OldM); |
| + EXPECT_EQ(1U, Finder.subprogram_count()); |
| +} |
| + |
| TEST_F(CloneModule, Subprogram) { |
| Function *NewF = NewM->getFunction("f"); |
| DISubprogram *SP = NewF->getSubprogram(); |