Skip to content

[DebugInfo][RemoveDIs] Instrument inliner for non-instr debug-info #72884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions llvm/include/llvm/IR/DebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,12 @@ class DebugInfoFinder {
/// Process a single instruction and collect debug info anchors.
void processInstruction(const Module &M, const Instruction &I);

/// Process DbgVariableIntrinsic.
void processVariable(const Module &M, const DbgVariableIntrinsic &DVI);
/// Process a DILocalVariable.
void processVariable(const Module &M, const DILocalVariable *DVI);
/// Process debug info location.
void processLocation(const Module &M, const DILocation *Loc);
// Process a DPValue, much like a DbgVariableIntrinsic.
void processDPValue(const Module &M, const DPValue &DPV);

/// Process subprogram.
void processSubprogram(DISubprogram *SP);
Expand Down
20 changes: 10 additions & 10 deletions llvm/lib/IR/DebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,10 +205,13 @@ void DebugInfoFinder::processCompileUnit(DICompileUnit *CU) {
void DebugInfoFinder::processInstruction(const Module &M,
const Instruction &I) {
if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I))
processVariable(M, *DVI);
processVariable(M, DVI->getVariable());

if (auto DbgLoc = I.getDebugLoc())
processLocation(M, DbgLoc.get());

for (const DPValue &DPV : I.getDbgValueRange())
processDPValue(M, DPV);
}

void DebugInfoFinder::processLocation(const Module &M, const DILocation *Loc) {
Expand All @@ -218,6 +221,11 @@ void DebugInfoFinder::processLocation(const Module &M, const DILocation *Loc) {
processLocation(M, Loc->getInlinedAt());
}

void DebugInfoFinder::processDPValue(const Module &M, const DPValue &DPV) {
processVariable(M, DPV.getVariable());
processLocation(M, DPV.getDebugLoc().get());
}

void DebugInfoFinder::processType(DIType *DT) {
if (!addType(DT))
return;
Expand Down Expand Up @@ -292,15 +300,7 @@ void DebugInfoFinder::processSubprogram(DISubprogram *SP) {
}

void DebugInfoFinder::processVariable(const Module &M,
const DbgVariableIntrinsic &DVI) {
auto *N = dyn_cast<MDNode>(DVI.getVariable());
if (!N)
return;

auto *DV = dyn_cast<DILocalVariable>(N);
if (!DV)
return;

const DILocalVariable *DV) {
if (!NodesSeen.insert(DV).second)
return;
processScope(DV->getScope());
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Scalar/CallSiteSplitting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ static void splitCallSite(CallBase &CB,
NewPN->insertBefore(&*TailBB->begin());
CurrentI->replaceAllUsesWith(NewPN);
}
CurrentI->dropDbgValues();
CurrentI->eraseFromParent();
// We are done once we handled the first original instruction in TailBB.
if (CurrentI == OriginalBegin)
Expand Down
5 changes: 3 additions & 2 deletions llvm/lib/Transforms/Scalar/JumpThreading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3064,8 +3064,8 @@ bool JumpThreadingPass::threadGuard(BasicBlock *BB, IntrinsicInst *Guard,
if (!isa<PHINode>(&*BI))
ToRemove.push_back(&*BI);

Instruction *InsertionPoint = &*BB->getFirstInsertionPt();
assert(InsertionPoint && "Empty block?");
BasicBlock::iterator InsertionPoint = BB->getFirstInsertionPt();
assert(InsertionPoint != BB->end() && "Empty block?");
// Substitute with Phis & remove.
for (auto *Inst : reverse(ToRemove)) {
if (!Inst->use_empty()) {
Expand All @@ -3075,6 +3075,7 @@ bool JumpThreadingPass::threadGuard(BasicBlock *BB, IntrinsicInst *Guard,
NewPN->insertBefore(InsertionPoint);
Inst->replaceAllUsesWith(NewPN);
}
Inst->dropDbgValues();
Inst->eraseFromParent();
}
return true;
Expand Down
60 changes: 55 additions & 5 deletions llvm/lib/Transforms/Utils/CloneFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,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
Expand Down Expand Up @@ -268,9 +269,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
Expand Down Expand Up @@ -328,6 +333,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();
Expand Down Expand Up @@ -493,6 +499,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;
Expand Down Expand Up @@ -542,6 +564,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))
Expand Down Expand Up @@ -599,6 +623,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) {
Expand All @@ -610,6 +637,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) {
Expand Down Expand Up @@ -847,12 +881,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);

Expand Down Expand Up @@ -941,10 +985,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
Expand Down Expand Up @@ -1068,6 +1117,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.
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Transforms/Utils/CloneModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ std::unique_ptr<Module> llvm::CloneModule(
New->setDataLayout(M.getDataLayout());
New->setTargetTriple(M.getTargetTriple());
New->setModuleInlineAsm(M.getModuleInlineAsm());
New->IsNewDbgInfoFormat = M.IsNewDbgInfoFormat;

// Loop over all of the global variables, making corresponding globals in the
// new module. Here we add them to the VMap and to the new Module. We
Expand Down
101 changes: 63 additions & 38 deletions llvm/lib/Transforms/Utils/InlineFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -1717,11 +1740,12 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI,
if (isa<DbgInfoIntrinsic>(BI)) {
BI = BI->eraseFromParent();
continue;
} else {
BI->dropDbgValues();
}
++BI;
}
}

}
}

Expand Down Expand Up @@ -2404,6 +2428,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);
}
Expand Down
Loading