aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/CloneFunction.cpp
diff options
context:
space:
mode:
authorJeremy Morse <jeremy.morse@sony.com>2023-11-26 21:24:29 +0000
committerGitHub <noreply@github.com>2023-11-26 21:24:29 +0000
commitc672ba7dde3a6ec2f6c89fcb207c9a6a8474cedc (patch)
treefcd978aedc24c8eb4b68251ad16cdda0310b5ba2 /llvm/lib/Transforms/Utils/CloneFunction.cpp
parentf4a4e2f85d819f44772b29c12a6cd2b86c14d611 (diff)
downloadllvm-c672ba7dde3a6ec2f6c89fcb207c9a6a8474cedc.zip
llvm-c672ba7dde3a6ec2f6c89fcb207c9a6a8474cedc.tar.gz
llvm-c672ba7dde3a6ec2f6c89fcb207c9a6a8474cedc.tar.bz2
[DebugInfo][RemoveDIs] Instrument inliner for non-instr debug-info (#72884)
With intrinsics representing debug-info, we just clone all the intrinsics when inlining a function and don't think about it any further. With non-instruction debug-info however we need to be a bit more careful and manually move the debug-info from one place to another. For the most part, this means keeping a "cursor" during block cloning of where we last copied debug-info from, and performing debug-info copying whenever we successfully clone another instruction. There are several utilities in LLVM for doing this, all of which now need to manually call cloneDebugInfo. The testing story for this is not well covered as we could rely on normal instruction-cloning mechanisms to do all the hard stuff. Thus, I've added a few tests to explicitly test dbg.value behaviours, ahead of them becoming not-instructions.
Diffstat (limited to 'llvm/lib/Transforms/Utils/CloneFunction.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/CloneFunction.cpp60
1 files changed, 55 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index 9ff4f01..abf0ab4 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -94,6 +94,7 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
const char *NameSuffix, ClonedCodeInfo *CodeInfo,
ValueMapTypeRemapper *TypeMapper,
ValueMaterializer *Materializer) {
+ NewFunc->setIsNewDbgInfoFormat(OldFunc->IsNewDbgInfoFormat);
assert(NameSuffix && "NameSuffix cannot be null!");
#ifndef NDEBUG
@@ -271,9 +272,13 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
BB = cast<BasicBlock>(VMap[&OldFunc->front()])->getIterator(),
BE = NewFunc->end();
BB != BE; ++BB)
- // Loop over all instructions, fixing each one as we find it...
- for (Instruction &II : *BB)
+ // Loop over all instructions, fixing each one as we find it, and any
+ // attached debug-info records.
+ for (Instruction &II : *BB) {
RemapInstruction(&II, VMap, RemapFlag, TypeMapper, Materializer);
+ RemapDPValueRange(II.getModule(), II.getDbgValueRange(), VMap, RemapFlag,
+ TypeMapper, Materializer);
+ }
// Only update !llvm.dbg.cu for DifferentModule (not CloneModule). In the
// same module, the compile unit will already be listed (or not). When
@@ -331,6 +336,7 @@ Function *llvm::CloneFunction(Function *F, ValueToValueMapTy &VMap,
// Create the new function...
Function *NewF = Function::Create(FTy, F->getLinkage(), F->getAddressSpace(),
F->getName(), F->getParent());
+ NewF->setIsNewDbgInfoFormat(F->IsNewDbgInfoFormat);
// Loop over the arguments, copying the names of the mapped arguments over...
Function::arg_iterator DestI = NewF->arg_begin();
@@ -496,6 +502,22 @@ void PruningFunctionCloner::CloneBlock(
bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false;
bool hasMemProfMetadata = false;
+ // Keep a cursor pointing at the last place we cloned debug-info records from.
+ BasicBlock::const_iterator DbgCursor = StartingInst;
+ auto CloneDbgRecordsToHere =
+ [NewBB, &DbgCursor](Instruction *NewInst, BasicBlock::const_iterator II) {
+ if (!NewBB->IsNewDbgInfoFormat)
+ return;
+
+ // Clone debug-info records onto this instruction. Iterate through any
+ // source-instructions we've cloned and then subsequently optimised
+ // away, so that their debug-info doesn't go missing.
+ for (; DbgCursor != II; ++DbgCursor)
+ NewInst->cloneDebugInfoFrom(&*DbgCursor, std::nullopt, false);
+ NewInst->cloneDebugInfoFrom(&*II);
+ DbgCursor = std::next(II);
+ };
+
// Loop over all instructions, and copy them over, DCE'ing as we go. This
// loop doesn't include the terminator.
for (BasicBlock::const_iterator II = StartingInst, IE = --BB->end(); II != IE;
@@ -545,6 +567,8 @@ void PruningFunctionCloner::CloneBlock(
hasMemProfMetadata |= II->hasMetadata(LLVMContext::MD_memprof);
}
+ CloneDbgRecordsToHere(NewInst, II);
+
if (CodeInfo) {
CodeInfo->OrigVMap[&*II] = NewInst;
if (auto *CB = dyn_cast<CallBase>(&*II))
@@ -602,6 +626,9 @@ void PruningFunctionCloner::CloneBlock(
if (OldTI->hasName())
NewInst->setName(OldTI->getName() + NameSuffix);
NewInst->insertInto(NewBB, NewBB->end());
+
+ CloneDbgRecordsToHere(NewInst, OldTI->getIterator());
+
VMap[OldTI] = NewInst; // Add instruction map to value.
if (CodeInfo) {
@@ -613,6 +640,13 @@ void PruningFunctionCloner::CloneBlock(
// Recursively clone any reachable successor blocks.
append_range(ToClone, successors(BB->getTerminator()));
+ } else {
+ // If we didn't create a new terminator, clone DPValues from the old
+ // terminator onto the new terminator.
+ Instruction *NewInst = NewBB->getTerminator();
+ assert(NewInst);
+
+ CloneDbgRecordsToHere(NewInst, OldTI->getIterator());
}
if (CodeInfo) {
@@ -850,12 +884,22 @@ void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
TypeMapper, Materializer);
}
+ // Do the same for DPValues, touching all the instructions in the cloned
+ // range of blocks.
+ Function::iterator Begin = cast<BasicBlock>(VMap[StartingBB])->getIterator();
+ for (BasicBlock &BB : make_range(Begin, NewFunc->end())) {
+ for (Instruction &I : BB) {
+ RemapDPValueRange(I.getModule(), I.getDbgValueRange(), 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
// basic block. That may leave some here, and we still want to prune the dead
// code as early as possible.
- Function::iterator Begin = cast<BasicBlock>(VMap[StartingBB])->getIterator();
for (BasicBlock &BB : make_range(Begin, NewFunc->end()))
ConstantFoldTerminator(&BB);
@@ -944,10 +988,15 @@ void llvm::CloneAndPruneFunctionInto(
void llvm::remapInstructionsInBlocks(ArrayRef<BasicBlock *> Blocks,
ValueToValueMapTy &VMap) {
// Rewrite the code to refer to itself.
- for (auto *BB : Blocks)
- for (auto &Inst : *BB)
+ for (auto *BB : Blocks) {
+ Module *M = BB->getModule();
+ for (auto &Inst : *BB) {
+ RemapDPValueRange(Inst.getModule(), Inst.getDbgValueRange(), VMap,
+ RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
RemapInstruction(&Inst, VMap,
RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
+ }
+ }
}
/// Clones a loop \p OrigLoop. Returns the loop and the blocks in \p
@@ -1071,6 +1120,7 @@ BasicBlock *llvm::DuplicateInstructionsInSplitBetween(
Instruction *New = BI->clone();
New->setName(BI->getName());
New->insertBefore(NewTerm);
+ New->cloneDebugInfoFrom(&*BI);
ValueMapping[&*BI] = New;
// Remap operands to patch up intra-block references.