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. /// in an imported function.
void findNeededSubprograms(); 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 /// The value mapper leaves nulls in the list of subprograms for any
/// in the UnneededSubprograms map. Strip those out after metadata linking. /// in the UnneededSubprograms map. Strip those out after metadata linking.
void stripNullSubprograms(); void stripNullSubprograms();
@ -1194,6 +1199,21 @@ bool IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) {
return false; 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() { void IRLinker::findNeededSubprograms() {
// Track unneeded nodes to make it simpler to handle the case // Track unneeded nodes to make it simpler to handle the case
// where we are checking if an already-mapped SP is needed. // where we are checking if an already-mapped SP is needed.
@ -1231,17 +1251,18 @@ void IRLinker::findNeededSubprograms() {
if (!IsMetadataLinkingPostpass) if (!IsMetadataLinkingPostpass)
return; return;
// In the case of metadata linking as a postpass (e.g. for function // In the case of metadata linking as a postpass (e.g. for function
// importing), see which DISubprogram MD from the source has an associated // importing), see which MD from the source has an associated
// temporary metadata node, which means the SP was needed by an imported // temporary metadata node, which means that any DISubprogram
// function. // reached from that MD was needed by an imported function.
SmallPtrSet<const MDNode *, 16> Visited;
for (auto MDI : MetadataToIDs) { for (auto MDI : MetadataToIDs) {
const MDNode *Node = dyn_cast<MDNode>(MDI.first); const MDNode *Node = dyn_cast<MDNode>(MDI.first);
if (!Node) if (!Node)
continue; continue;
DISubprogram *SP = getDISubprogram(Node); if (!ValIDToTempMDMap->count(MDI.second))
if (!SP || !ValIDToTempMDMap->count(MDI.second))
continue; 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: distinct !DISubprogram(name: "func1"
; CHECK-NOT: distinct !DISubprogram(name: "func2" ; CHECK-NOT: distinct !DISubprogram(name: "func2"
; CHECK: distinct !DISubprogram(name: "func3"
; CHECK: distinct !DISubprogram(name: "func4"
; ModuleID = 'dbg.o' ; 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) !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: ".") !1 = !DIFile(filename: "dbg.c", directory: ".")
!2 = !{} !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) !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) !5 = !DISubroutineType(types: !6)
!6 = !{!7, !7} !6 = !{!7, !7}
@ -72,9 +74,17 @@ attributes #1 = { nounwind readnone }
!17 = !DIExpression() !17 = !DIExpression()
!18 = !DILocation(line: 1, column: 15, scope: !4) !18 = !DILocation(line: 1, column: 15, scope: !4)
!19 = !DILocation(line: 2, column: 7, scope: !4) !19 = !DILocation(line: 2, column: 7, scope: !4)
!20 = !DILocation(line: 3, column: 9, scope: !21) !20 = !DILocation(line: 3, column: 9, scope: !21, inlinedAt: !26)
!21 = distinct !DILexicalBlock(scope: !4, file: !1, line: 3, column: 7) !21 = distinct !DILexicalBlock(scope: !27, file: !1, line: 3, column: 7)
!22 = !DILocation(line: 3, column: 7, scope: !4) !22 = !DILocation(line: 3, column: 7, scope: !4)
!23 = !DILocation(line: 5, column: 3, scope: !4) !23 = !DILocation(line: 5, column: 3, scope: !4)
!24 = !DILocation(line: 8, column: 15, scope: !11) !24 = !DILocation(line: 8, column: 15, scope: !11)
!25 = !DILocation(line: 9, column: 3, 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)