1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 12:12:47 +01:00

[ThinLTO] Find all needed metadata when linking metadata as postpass

For metadata postpass linking, after importing all functions, we need
to recursively walk through any nodes reached via imported functions to
locate needed subprogram metadata. Some might only be reached indirectly
via the variable list for an inlined function.

llvm-svn: 258728
This commit is contained in:
Teresa Johnson 2016-01-25 22:04:56 +00:00
parent a63717e4c0
commit a52cfbb4e3
2 changed files with 40 additions and 9 deletions

View File

@ -501,6 +501,11 @@ class IRLinker {
/// in an imported function.
void findNeededSubprograms();
/// Recursive helper for findNeededSubprograms to locate any DISubprogram
/// reached from the given Node, marking any found as needed.
void findReachedSubprograms(const MDNode *Node,
SmallPtrSet<const MDNode *, 16> &Visited);
/// The value mapper leaves nulls in the list of subprograms for any
/// in the UnneededSubprograms map. Strip those out after metadata linking.
void stripNullSubprograms();
@ -1194,6 +1199,21 @@ bool IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) {
return false;
}
void IRLinker::findReachedSubprograms(
const MDNode *Node, SmallPtrSet<const MDNode *, 16> &Visited) {
if (!Visited.insert(Node).second)
return;
DISubprogram *SP = getDISubprogram(Node);
if (SP)
UnneededSubprograms.erase(SP);
for (auto &Op : Node->operands()) {
const MDNode *OpN = dyn_cast_or_null<MDNode>(Op.get());
if (!OpN)
continue;
findReachedSubprograms(OpN, Visited);
}
}
void IRLinker::findNeededSubprograms() {
// Track unneeded nodes to make it simpler to handle the case
// where we are checking if an already-mapped SP is needed.
@ -1231,17 +1251,18 @@ void IRLinker::findNeededSubprograms() {
if (!IsMetadataLinkingPostpass)
return;
// In the case of metadata linking as a postpass (e.g. for function
// importing), see which DISubprogram MD from the source has an associated
// temporary metadata node, which means the SP was needed by an imported
// function.
// importing), see which MD from the source has an associated
// temporary metadata node, which means that any DISubprogram
// reached from that MD was needed by an imported function.
SmallPtrSet<const MDNode *, 16> Visited;
for (auto MDI : MetadataToIDs) {
const MDNode *Node = dyn_cast<MDNode>(MDI.first);
if (!Node)
continue;
DISubprogram *SP = getDISubprogram(Node);
if (!SP || !ValIDToTempMDMap->count(MDI.second))
if (!ValIDToTempMDMap->count(MDI.second))
continue;
UnneededSubprograms.erase(SP);
// Find any SP needed recursively from this needed Node.
findReachedSubprograms(Node, Visited);
}
}

View File

@ -18,6 +18,8 @@
; CHECK: distinct !DISubprogram(name: "func1"
; CHECK-NOT: distinct !DISubprogram(name: "func2"
; CHECK: distinct !DISubprogram(name: "func3"
; CHECK: distinct !DISubprogram(name: "func4"
; ModuleID = 'dbg.o'
@ -55,7 +57,7 @@ attributes #1 = { nounwind readnone }
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0 (trunk 251407) (llvm/trunk 251401)", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3)
!1 = !DIFile(filename: "dbg.c", directory: ".")
!2 = !{}
!3 = !{!4, !11}
!3 = !{!4, !11, !27, !30}
!4 = distinct !DISubprogram(name: "func1", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, variables: !8)
!5 = !DISubroutineType(types: !6)
!6 = !{!7, !7}
@ -72,9 +74,17 @@ attributes #1 = { nounwind readnone }
!17 = !DIExpression()
!18 = !DILocation(line: 1, column: 15, scope: !4)
!19 = !DILocation(line: 2, column: 7, scope: !4)
!20 = !DILocation(line: 3, column: 9, scope: !21)
!21 = distinct !DILexicalBlock(scope: !4, file: !1, line: 3, column: 7)
!20 = !DILocation(line: 3, column: 9, scope: !21, inlinedAt: !26)
!21 = distinct !DILexicalBlock(scope: !27, file: !1, line: 3, column: 7)
!22 = !DILocation(line: 3, column: 7, scope: !4)
!23 = !DILocation(line: 5, column: 3, scope: !4)
!24 = !DILocation(line: 8, column: 15, scope: !11)
!25 = !DILocation(line: 9, column: 3, scope: !11)
!26 = !DILocation(line: 9, column: 3, scope: !4)
!27 = distinct !DISubprogram(name: "func3", scope: !1, file: !1, line: 8, type: !5, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, variables: !28)
!28 = !{!29}
!29 = !DILocalVariable(name: "n", arg: 1, scope: !30, file: !1, line: 8, type: !7)
!30 = distinct !DISubprogram(name: "func4", scope: !1, file: !1, line: 8, type: !5, isLocal: false, isDefinition: true, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true, variables: !31)
!31 = !{!32}
!32 = !DILocalVariable(name: "n", arg: 1, scope: !30, file: !1, line: 8, type: !7)