Skip to content

Commit

Permalink
Merge pull request llvm#3006 from adrian-prantl/78487175-5.4
Browse files Browse the repository at this point in the history
Support stripping indirectly referenced DILocations from !llvm.loop m…
  • Loading branch information
adrian-prantl authored May 27, 2021
2 parents cee6210 + 0f5ed64 commit 9205ffc
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 9205ffc

Please sign in to comment.