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:
parent
a63717e4c0
commit
a52cfbb4e3
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user