diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Utils/CloneFunction.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/Utils/CloneFunction.cpp | 88 |
1 files changed, 67 insertions, 21 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Utils/CloneFunction.cpp b/contrib/llvm-project/llvm/lib/Transforms/Utils/CloneFunction.cpp index 1d348213bfdb..87822ee85c2b 100644 --- a/contrib/llvm-project/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/contrib/llvm-project/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -33,6 +33,7 @@ #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/ValueMapper.h" #include <map> +#include <optional> using namespace llvm; #define DEBUG_TYPE "clone-function" @@ -46,7 +47,7 @@ BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, if (BB->hasName()) NewBB->setName(BB->getName() + NameSuffix); - bool hasCalls = false, hasDynamicAllocas = false; + bool hasCalls = false, hasDynamicAllocas = false, hasMemProfMetadata = false; Module *TheModule = F ? F->getParent() : nullptr; // Loop over all instructions, and copy them over. @@ -57,10 +58,13 @@ BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, Instruction *NewInst = I.clone(); if (I.hasName()) NewInst->setName(I.getName() + NameSuffix); - NewBB->getInstList().push_back(NewInst); + NewInst->insertInto(NewBB, NewBB->end()); VMap[&I] = NewInst; // Add instruction map to value. - hasCalls |= (isa<CallInst>(I) && !I.isDebugOrPseudoInst()); + if (isa<CallInst>(I) && !I.isDebugOrPseudoInst()) { + hasCalls = true; + hasMemProfMetadata |= I.hasMetadata(LLVMContext::MD_memprof); + } if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) { if (!AI->isStaticAlloca()) { hasDynamicAllocas = true; @@ -70,6 +74,7 @@ BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap, if (CodeInfo) { CodeInfo->ContainsCalls |= hasCalls; + CodeInfo->ContainsMemProfMetadata |= hasMemProfMetadata; CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas; } return NewBB; @@ -100,12 +105,26 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, NewFunc->copyAttributesFrom(OldFunc); NewFunc->setAttributes(NewAttrs); + const RemapFlags FuncGlobalRefFlags = + ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges; + // Fix up the personality function that got copied over. if (OldFunc->hasPersonalityFn()) - NewFunc->setPersonalityFn( - MapValue(OldFunc->getPersonalityFn(), VMap, - ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, - TypeMapper, Materializer)); + NewFunc->setPersonalityFn(MapValue(OldFunc->getPersonalityFn(), VMap, + FuncGlobalRefFlags, TypeMapper, + Materializer)); + + if (OldFunc->hasPrefixData()) { + NewFunc->setPrefixData(MapValue(OldFunc->getPrefixData(), VMap, + FuncGlobalRefFlags, TypeMapper, + Materializer)); + } + + if (OldFunc->hasPrologueData()) { + NewFunc->setPrologueData(MapValue(OldFunc->getPrologueData(), VMap, + FuncGlobalRefFlags, TypeMapper, + Materializer)); + } SmallVector<AttributeSet, 4> NewArgAttrs(NewFunc->arg_size()); AttributeList OldAttrs = OldFunc->getAttributes(); @@ -132,7 +151,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc, // duplicate instructions and then freeze them in the MD map. We also record // information about dbg.value and dbg.declare to avoid duplicating the // types. - Optional<DebugInfoFinder> DIFinder; + std::optional<DebugInfoFinder> DIFinder; // Track the subprogram attachment that needs to be cloned to fine-tune the // mapping within the same module. @@ -471,6 +490,7 @@ void PruningFunctionCloner::CloneBlock( } bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false; + bool hasMemProfMetadata = false; // Loop over all instructions, and copy them over, DCE'ing as we go. This // loop doesn't include the terminator. @@ -487,8 +507,9 @@ void PruningFunctionCloner::CloneBlock( } // Eagerly remap operands to the newly cloned instruction, except for PHI - // nodes for which we defer processing until we update the CFG. - if (!isa<PHINode>(NewInst)) { + // nodes for which we defer processing until we update the CFG. Also defer + // debug intrinsic processing because they may contain use-before-defs. + if (!isa<PHINode>(NewInst) && !isa<DbgVariableIntrinsic>(NewInst)) { RemapInstruction(NewInst, VMap, ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges); @@ -514,8 +535,11 @@ void PruningFunctionCloner::CloneBlock( if (II->hasName()) NewInst->setName(II->getName() + NameSuffix); VMap[&*II] = NewInst; // Add instruction map to value. - NewBB->getInstList().push_back(NewInst); - hasCalls |= (isa<CallInst>(II) && !II->isDebugOrPseudoInst()); + NewInst->insertInto(NewBB, NewBB->end()); + if (isa<CallInst>(II) && !II->isDebugOrPseudoInst()) { + hasCalls = true; + hasMemProfMetadata |= II->hasMetadata(LLVMContext::MD_memprof); + } if (CodeInfo) { CodeInfo->OrigVMap[&*II] = NewInst; @@ -573,7 +597,7 @@ void PruningFunctionCloner::CloneBlock( Instruction *NewInst = OldTI->clone(); if (OldTI->hasName()) NewInst->setName(OldTI->getName() + NameSuffix); - NewBB->getInstList().push_back(NewInst); + NewInst->insertInto(NewBB, NewBB->end()); VMap[OldTI] = NewInst; // Add instruction map to value. if (CodeInfo) { @@ -589,6 +613,7 @@ void PruningFunctionCloner::CloneBlock( if (CodeInfo) { CodeInfo->ContainsCalls |= hasCalls; + CodeInfo->ContainsMemProfMetadata |= hasMemProfMetadata; CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas; CodeInfo->ContainsDynamicAllocas |= hasStaticAllocas && BB != &BB->getParent()->front(); @@ -628,6 +653,15 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, StartingInst = &StartingBB->front(); } + // Collect debug intrinsics for remapping later. + SmallVector<const DbgVariableIntrinsic *, 8> DbgIntrinsics; + for (const auto &BB : *OldFunc) { + for (const auto &I : BB) { + if (const auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) + DbgIntrinsics.push_back(DVI); + } + } + // Clone the entry block, and anything recursively reachable from it. std::vector<const BasicBlock *> CloneWorklist; PFC.CloneBlock(StartingBB, StartingInst->getIterator(), CloneWorklist); @@ -650,7 +684,7 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, continue; // Dead block. // Add the new block to the new function. - NewFunc->getBasicBlockList().push_back(NewBB); + NewFunc->insert(NewFunc->end(), NewBB); // Handle PHI nodes specially, as we have to remove references to dead // blocks. @@ -799,6 +833,19 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, VMap[OrigV] = I; } + // Remap debug intrinsic operands now that all values have been mapped. + // Doing this now (late) preserves use-before-defs in debug intrinsics. If + // we didn't do this, ValueAsMetadata(use-before-def) operands would be + // replaced by empty metadata. This would signal later cleanup passes to + // remove the debug intrinsics, potentially causing incorrect locations. + for (const auto *DVI : DbgIntrinsics) { + if (DbgVariableIntrinsic *NewDVI = + cast_or_null<DbgVariableIntrinsic>(VMap.lookup(DVI))) + RemapInstruction(NewDVI, VMap, + ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges, + TypeMapper, Materializer); + } + // Simplify conditional branches and switches with a constant operand. We try // to prune these out when cloning, but if the simplification required // looking through PHI nodes, those are only available after forming the full @@ -856,7 +903,7 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc, Dest->replaceAllUsesWith(&*I); // Move all the instructions in the succ to the pred. - I->getInstList().splice(I->end(), Dest->getInstList()); + I->splice(I->end(), Dest); // Remove the dest block. Dest->eraseFromParent(); @@ -980,10 +1027,9 @@ Loop *llvm::cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB, } // Move them physically from the end of the block list. - F->getBasicBlockList().splice(Before->getIterator(), F->getBasicBlockList(), - NewPH); - F->getBasicBlockList().splice(Before->getIterator(), F->getBasicBlockList(), - NewLoop->getHeader()->getIterator(), F->end()); + F->splice(Before->getIterator(), F, NewPH->getIterator()); + F->splice(Before->getIterator(), F, NewLoop->getHeader()->getIterator(), + F->end()); return NewLoop; } @@ -1041,7 +1087,7 @@ void llvm::cloneNoAliasScopes(ArrayRef<MDNode *> NoAliasDeclScopes, MDBuilder MDB(Context); for (auto *ScopeList : NoAliasDeclScopes) { - for (auto &MDOperand : ScopeList->operands()) { + for (const auto &MDOperand : ScopeList->operands()) { if (MDNode *MD = dyn_cast<MDNode>(MDOperand)) { AliasScopeNode SNANode(MD); @@ -1066,7 +1112,7 @@ void llvm::adaptNoAliasScopes(Instruction *I, auto CloneScopeList = [&](const MDNode *ScopeList) -> MDNode * { bool NeedsReplacement = false; SmallVector<Metadata *, 8> NewScopeList; - for (auto &MDOp : ScopeList->operands()) { + for (const auto &MDOp : ScopeList->operands()) { if (MDNode *MD = dyn_cast<MDNode>(MDOp)) { if (auto *NewMD = ClonedScopes.lookup(MD)) { NewScopeList.push_back(NewMD); |