Skip to content

Commit

Permalink
Support stripping indirectly referenced DILocations from !llvm.loop m…
Browse files Browse the repository at this point in the history
…etadata

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

(cherry picked from commit df6622f789b7a26612ba25e3af036153213ce502)
  • Loading branch information
adrian-prantl committed May 27, 2021
1 parent cee6210 commit 0f5ed64
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 32 deletions.
6 changes: 3 additions & 3 deletions llvm/include/llvm/IR/DebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,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);
Expand Down
82 changes: 60 additions & 22 deletions llvm/lib/IR/DebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,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 &&
Expand All @@ -274,11 +273,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);
Expand All @@ -288,34 +286,72 @@ 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;
MDNode *NewLoopID = updateLoopMetadataDebugLocationsImpl(OrigLoopID, Updater);
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) {
Expand All @@ -325,7 +361,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.
Expand Down Expand Up @@ -657,8 +693,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.
Expand Down
9 changes: 5 additions & 4 deletions llvm/lib/Transforms/Utils/CodeExtractor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1509,10 +1509,11 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
I.setDebugLoc(DebugLoc::get(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);
}
Expand Down
8 changes: 5 additions & 3 deletions llvm/lib/Transforms/Utils/InlineFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1483,9 +1483,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);

Expand Down
25 changes: 25 additions & 0 deletions llvm/test/Verifier/llvm.loop-cu-strip-indirect.ll
Original file line number Diff line number Diff line change
@@ -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)

0 comments on commit 0f5ed64

Please sign in to comment.