Support stripping indirectly referenced DILocations from !llvm.loop metadata

in stripDebugInfo().  This patch fixes an oversight in
https://reviews.llvm.org/D96181 and also takes into account loop
metadata pointing to other MDNodes that point into the debug info.

rdar://78487175

Differential Revision: https://reviews.llvm.org/D103220
This commit is contained in:
Adrian Prantl 2021-05-26 18:23:02 -07:00
parent 50f17e9d31
commit f3869a5c32
5 changed files with 98 additions and 32 deletions

View File

@ -70,11 +70,11 @@ bool stripDebugInfo(Function &F);
bool stripNonLineTableDebugInfo(Module &M);
/// Update the debug locations contained within the MD_loop metadata attached
/// to the instruction \p I, if one exists. \p Updater is applied to each debug
/// location in the MD_loop metadata: the returned value is included in the
/// to the instruction \p I, if one exists. \p Updater is applied to Metadata
/// operand in the MD_loop metadata: the returned value is included in the
/// updated loop metadata node if it is non-null.
void updateLoopMetadataDebugLocations(
Instruction &I, function_ref<DILocation *(const DILocation &)> Updater);
Instruction &I, function_ref<Metadata *(Metadata *)> Updater);
/// Return Debug Info Metadata Version by checking module flags.
unsigned getDebugMetadataVersionFromModule(const Module &M);

View File

@ -348,8 +348,7 @@ bool DebugInfoFinder::addScope(DIScope *Scope) {
}
static MDNode *updateLoopMetadataDebugLocationsImpl(
MDNode *OrigLoopID,
function_ref<DILocation *(const DILocation &)> Updater) {
MDNode *OrigLoopID, function_ref<Metadata *(Metadata *)> Updater) {
assert(OrigLoopID && OrigLoopID->getNumOperands() > 0 &&
"Loop ID needs at least one operand");
assert(OrigLoopID && OrigLoopID->getOperand(0).get() == OrigLoopID &&
@ -360,11 +359,10 @@ static MDNode *updateLoopMetadataDebugLocationsImpl(
for (unsigned i = 1; i < OrigLoopID->getNumOperands(); ++i) {
Metadata *MD = OrigLoopID->getOperand(i);
if (DILocation *DL = dyn_cast<DILocation>(MD)) {
if (DILocation *NewDL = Updater(*DL))
MDs.push_back(NewDL);
} else
MDs.push_back(MD);
if (!MD)
MDs.push_back(nullptr);
else if (Metadata *NewMD = Updater(MD))
MDs.push_back(NewMD);
}
MDNode *NewLoopID = MDNode::getDistinct(OrigLoopID->getContext(), MDs);
@ -374,7 +372,7 @@ static MDNode *updateLoopMetadataDebugLocationsImpl(
}
void llvm::updateLoopMetadataDebugLocations(
Instruction &I, function_ref<DILocation *(const DILocation &)> Updater) {
Instruction &I, function_ref<Metadata *(Metadata *)> Updater) {
MDNode *OrigLoopID = I.getMetadata(LLVMContext::MD_loop);
if (!OrigLoopID)
return;
@ -382,26 +380,64 @@ void llvm::updateLoopMetadataDebugLocations(
I.setMetadata(LLVMContext::MD_loop, NewLoopID);
}
/// Return true if a node is a DILocation or if a DILocation is
/// indirectly referenced by one of the node's children.
static bool isDILocationReachable(SmallPtrSetImpl<Metadata *> &Visited,
SmallPtrSetImpl<Metadata *> &Reachable,
Metadata *MD) {
MDNode *N = dyn_cast_or_null<MDNode>(MD);
if (!N)
return false;
if (Reachable.count(N) || isa<DILocation>(N))
return true;
if (!Visited.insert(N).second)
return false;
for (auto &OpIt : N->operands()) {
Metadata *Op = OpIt.get();
if (isDILocationReachable(Visited, Reachable, Op)) {
Reachable.insert(N);
return true;
}
}
return false;
}
static MDNode *stripDebugLocFromLoopID(MDNode *N) {
assert(!N->operands().empty() && "Missing self reference?");
SmallPtrSet<Metadata *, 8> Visited, DILocationReachable;
// If we already visited N, there is nothing to do.
if (!Visited.insert(N).second)
return N;
// if there is no debug location, we do not have to rewrite this MDNode.
if (std::none_of(N->op_begin() + 1, N->op_end(), [](const MDOperand &Op) {
return isa<DILocation>(Op.get());
}))
// If there is no debug location, we do not have to rewrite this
// MDNode. This loop also initializes DILocationReachable, later
// needed by updateLoopMetadataDebugLocationsImpl; the use of
// count_if avoids an early exit.
if (!std::count_if(N->op_begin() + 1, N->op_end(),
[&Visited, &DILocationReachable](const MDOperand &Op) {
return isa<DILocation>(Op.get()) ||
isDILocationReachable(
Visited, DILocationReachable, Op.get());
}))
return N;
// If there is only the debug location without any actual loop metadata, we
// can remove the metadata.
if (std::none_of(N->op_begin() + 1, N->op_end(), [](const MDOperand &Op) {
return !isa<DILocation>(Op.get());
}))
if (std::all_of(
N->op_begin() + 1, N->op_end(),
[&Visited, &DILocationReachable](const MDOperand &Op) {
return isa<DILocation>(Op.get()) ||
isDILocationReachable(Visited, DILocationReachable,
Op.get());
}))
return nullptr;
auto dropDebugLoc = [](const DILocation &) -> DILocation * {
return nullptr;
};
return updateLoopMetadataDebugLocationsImpl(N, dropDebugLoc);
return updateLoopMetadataDebugLocationsImpl(
N, [&DILocationReachable](Metadata *MD) -> Metadata * {
if (isa<DILocation>(MD) || DILocationReachable.count(MD))
return nullptr;
return MD;
});
}
bool llvm::stripDebugInfo(Function &F) {
@ -411,7 +447,7 @@ bool llvm::stripDebugInfo(Function &F) {
F.setSubprogram(nullptr);
}
DenseMap<MDNode*, MDNode*> LoopIDsMap;
DenseMap<MDNode *, MDNode *> LoopIDsMap;
for (BasicBlock &BB : F) {
for (auto II = BB.begin(), End = BB.end(); II != End;) {
Instruction &I = *II++; // We may delete the instruction, increment now.
@ -740,8 +776,10 @@ bool llvm::stripNonLineTableDebugInfo(Module &M) {
I.setDebugLoc(remapDebugLoc(I.getDebugLoc()));
// Remap DILocations in llvm.loop attachments.
updateLoopMetadataDebugLocations(I, [&](const DILocation &Loc) {
return remapDebugLoc(&Loc).get();
updateLoopMetadataDebugLocations(I, [&](Metadata *MD) -> Metadata * {
if (auto *Loc = dyn_cast_or_null<DILocation>(MD))
return remapDebugLoc(Loc).get();
return MD;
});
// Strip heapallocsite attachments, they point into the DIType system.

View File

@ -1552,10 +1552,11 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
I.setDebugLoc(DILocation::get(Ctx, DL.getLine(), DL.getCol(), NewSP));
// Loop info metadata may contain line locations. Fix them up.
auto updateLoopInfoLoc = [&Ctx,
NewSP](const DILocation &Loc) -> DILocation * {
return DILocation::get(Ctx, Loc.getLine(), Loc.getColumn(), NewSP,
nullptr);
auto updateLoopInfoLoc = [&Ctx, NewSP](Metadata *MD) -> Metadata * {
if (auto *Loc = dyn_cast_or_null<DILocation>(MD))
return DILocation::get(Ctx, Loc->getLine(), Loc->getColumn(), NewSP,
nullptr);
return MD;
};
updateLoopMetadataDebugLocations(I, updateLoopInfoLoc);
}

View File

@ -1519,9 +1519,11 @@ static void fixupLineNumbers(Function *Fn, Function::iterator FI,
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](
const DILocation &Loc) -> DILocation * {
return inlineDebugLoc(&Loc, InlinedAtNode, Ctx, IANodes).get();
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);

View File

@ -0,0 +1,25 @@
; RUN: llvm-as -disable-output < %s -o /dev/null 2>&1 | FileCheck %s
; RUN: llvm-as < %s -o - | llvm-dis - | FileCheck %s --check-prefix=CHECK-STRIP
; CHECK: DICompileUnit not listed in llvm.dbg.cu
; CHECK: ignoring invalid debug info in
; CHECK-NOT: DICompileUnit not listed in llvm.dbg.cu
declare hidden void @g() local_unnamed_addr #1 align 2
define hidden void @f() {
tail call void @g() #2, !llvm.loop !5
ret void
}
!llvm.module.flags = !{!0, !1}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!5 = distinct !{!5, !14, !15, !"fake loop metadata"}
; CHECK-STRIP: ![[MD:.*]] = distinct !{![[MD]], !{{[0-9]+}}, !"fake loop metadata"}
!7 = distinct !DISubprogram(name: "f", scope: !8, file: !8, line: 1324, type: !9, scopeLine: 1324, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !11)
!8 = !DIFile(filename: "/", directory: "f.cpp")
!9 = !DISubroutineType(types: !10)
!10 = !{}
!11 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !8)
!14 = !{!"metadata 1", i1 true}
!15 = !{!"metadata 1", !16}
!16 = distinct !{!16, !17}
!17 = !DILocation(line: 105, column: 3, scope: !18)
!18 = distinct !DILexicalBlock(scope: !7, file: !8, line: 105, column: 3)