diff options
author | Jeremy Morse <jeremy.morse@sony.com> | 2023-11-26 21:24:29 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-26 21:24:29 +0000 |
commit | c672ba7dde3a6ec2f6c89fcb207c9a6a8474cedc (patch) | |
tree | fcd978aedc24c8eb4b68251ad16cdda0310b5ba2 /llvm/lib/Transforms/Utils/InlineFunction.cpp | |
parent | f4a4e2f85d819f44772b29c12a6cd2b86c14d611 (diff) | |
download | llvm-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/InlineFunction.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/InlineFunction.cpp | 101 |
1 files changed, 63 insertions, 38 deletions
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 6f36973..39d5f6e 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1666,48 +1666,71 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, // the call site location instead. bool NoInlineLineTables = Fn->hasFnAttribute("no-inline-line-tables"); - for (; FI != Fn->end(); ++FI) { - for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); - BI != BE; ++BI) { - // Loop metadata needs to be updated so that the start and end locs - // reference inlined-at locations. - auto updateLoopInfoLoc = [&Ctx, &InlinedAtNode, - &IANodes](Metadata *MD) -> Metadata * { - if (auto *Loc = dyn_cast_or_null<DILocation>(MD)) - return inlineDebugLoc(Loc, InlinedAtNode, Ctx, IANodes).get(); - return MD; - }; - updateLoopMetadataDebugLocations(*BI, updateLoopInfoLoc); - - if (!NoInlineLineTables) - if (DebugLoc DL = BI->getDebugLoc()) { - DebugLoc IDL = - inlineDebugLoc(DL, InlinedAtNode, BI->getContext(), IANodes); - BI->setDebugLoc(IDL); - continue; - } + // Helper-util for updating the metadata attached to an instruction. + auto UpdateInst = [&](Instruction &I) { + // Loop metadata needs to be updated so that the start and end locs + // reference inlined-at locations. + auto updateLoopInfoLoc = [&Ctx, &InlinedAtNode, + &IANodes](Metadata *MD) -> Metadata * { + if (auto *Loc = dyn_cast_or_null<DILocation>(MD)) + return inlineDebugLoc(Loc, InlinedAtNode, Ctx, IANodes).get(); + return MD; + }; + updateLoopMetadataDebugLocations(I, updateLoopInfoLoc); + + if (!NoInlineLineTables) + if (DebugLoc DL = I.getDebugLoc()) { + DebugLoc IDL = + inlineDebugLoc(DL, InlinedAtNode, I.getContext(), IANodes); + I.setDebugLoc(IDL); + return; + } - if (CalleeHasDebugInfo && !NoInlineLineTables) - continue; + if (CalleeHasDebugInfo && !NoInlineLineTables) + return; - // If the inlined instruction has no line number, or if inline info - // is not being generated, make it look as if it originates from the call - // location. This is important for ((__always_inline, __nodebug__)) - // functions which must use caller location for all instructions in their - // function body. + // If the inlined instruction has no line number, or if inline info + // is not being generated, make it look as if it originates from the call + // location. This is important for ((__always_inline, __nodebug__)) + // functions which must use caller location for all instructions in their + // function body. - // Don't update static allocas, as they may get moved later. - if (auto *AI = dyn_cast<AllocaInst>(BI)) - if (allocaWouldBeStaticInEntry(AI)) - continue; + // Don't update static allocas, as they may get moved later. + if (auto *AI = dyn_cast<AllocaInst>(&I)) + if (allocaWouldBeStaticInEntry(AI)) + return; - // Do not force a debug loc for pseudo probes, since they do not need to - // be debuggable, and also they are expected to have a zero/null dwarf - // discriminator at this point which could be violated otherwise. - if (isa<PseudoProbeInst>(BI)) - continue; + // Do not force a debug loc for pseudo probes, since they do not need to + // be debuggable, and also they are expected to have a zero/null dwarf + // discriminator at this point which could be violated otherwise. + if (isa<PseudoProbeInst>(I)) + return; + + I.setDebugLoc(TheCallDL); + }; - BI->setDebugLoc(TheCallDL); + // Helper-util for updating debug-info records attached to instructions. + auto UpdateDPV = [&](DPValue *DPV) { + assert(DPV->getDebugLoc() && "Debug Value must have debug loc"); + if (NoInlineLineTables) { + DPV->setDebugLoc(TheCallDL); + return; + } + DebugLoc DL = DPV->getDebugLoc(); + DebugLoc IDL = + inlineDebugLoc(DL, InlinedAtNode, + DPV->getMarker()->getParent()->getContext(), IANodes); + DPV->setDebugLoc(IDL); + }; + + // Iterate over all instructions, updating metadata and debug-info records. + for (; FI != Fn->end(); ++FI) { + for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; + ++BI) { + UpdateInst(*BI); + for (DPValue &DPV : BI->getDbgValueRange()) { + UpdateDPV(&DPV); + } } // Remove debug info intrinsics if we're not keeping inline info. @@ -1717,11 +1740,12 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI, if (isa<DbgInfoIntrinsic>(BI)) { BI = BI->eraseFromParent(); continue; + } else { + BI->dropDbgValues(); } ++BI; } } - } } @@ -2402,6 +2426,7 @@ llvm::InlineResult llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, // Transfer all of the allocas over in a block. Using splice means // that the instructions aren't removed from the symbol table, then // reinserted. + I.setTailBit(true); Caller->getEntryBlock().splice(InsertPoint, &*FirstNewBlock, AI->getIterator(), I); } |