forked from OSchip/llvm-project
[ELF] Read the call graph profile from object files.
This uses the call graph profile embedded in the object files to construct the call graph. This is read from a SHT_LLVM_CALL_GRAPH_PROFILE (0x6fff4c02) section as (uint32_t, uint32_t, uint64_t) tuples as (from symbol index, to symbol index, weight). Differential Revision: https://reviews.llvm.org/D45850 llvm-svn: 343552
This commit is contained in:
parent
d616d33a96
commit
8222f902ca
|
@ -679,6 +679,27 @@ static void readCallGraph(MemoryBufferRef MB) {
|
|||
}
|
||||
}
|
||||
|
||||
template <class ELFT> static void readCallGraphsFromObjectFiles() {
|
||||
auto FindSection = [&](const Symbol *Sym) -> const InputSectionBase * {
|
||||
warnUnorderableSymbol(Sym);
|
||||
if (const auto *SymD = dyn_cast<Defined>(Sym))
|
||||
return dyn_cast_or_null<InputSectionBase>(SymD->Section);
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
for (auto File : ObjectFiles) {
|
||||
auto *Obj = cast<ObjFile<ELFT>>(File);
|
||||
for (const Elf_CGProfile_Impl<ELFT> &CGPE : Obj->CGProfile) {
|
||||
const InputSectionBase *FromSB =
|
||||
FindSection(&Obj->getSymbol(CGPE.cgp_from));
|
||||
const InputSectionBase *ToSB = FindSection(&Obj->getSymbol(CGPE.cgp_to));
|
||||
if (!FromSB || !ToSB)
|
||||
continue;
|
||||
Config->CallGraphProfile[{FromSB, ToSB}] += CGPE.cgp_weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool getCompressDebugSections(opt::InputArgList &Args) {
|
||||
StringRef S = Args.getLastArgValue(OPT_compress_debug_sections, "none");
|
||||
if (S == "none")
|
||||
|
@ -1598,6 +1619,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
|
|||
if (auto *Arg = Args.getLastArg(OPT_call_graph_ordering_file))
|
||||
if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
|
||||
readCallGraph(*Buffer);
|
||||
readCallGraphsFromObjectFiles<ELFT>();
|
||||
|
||||
// Write the result to the file.
|
||||
writeResult<ELFT>();
|
||||
|
|
|
@ -412,6 +412,11 @@ void ObjFile<ELFT>::initializeSections(
|
|||
continue;
|
||||
const Elf_Shdr &Sec = ObjSections[I];
|
||||
|
||||
if (Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE)
|
||||
CGProfile = check(
|
||||
this->getObj().template getSectionContentsAsArray<Elf_CGProfile>(
|
||||
&Sec));
|
||||
|
||||
// SHF_EXCLUDE'ed sections are discarded by the linker. However,
|
||||
// if -r is given, we'll let the final link discard such sections.
|
||||
// This is compatible with GNU.
|
||||
|
|
|
@ -171,6 +171,7 @@ template <class ELFT> class ObjFile : public ELFFileBase<ELFT> {
|
|||
typedef typename ELFT::Sym Elf_Sym;
|
||||
typedef typename ELFT::Shdr Elf_Shdr;
|
||||
typedef typename ELFT::Word Elf_Word;
|
||||
typedef typename ELFT::CGProfile Elf_CGProfile;
|
||||
|
||||
StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
|
||||
const Elf_Shdr &Sec);
|
||||
|
@ -220,6 +221,9 @@ public:
|
|||
// Pointer to this input file's .llvm_addrsig section, if it has one.
|
||||
const Elf_Shdr *AddrsigSec = nullptr;
|
||||
|
||||
// SHT_LLVM_CALL_GRAPH_PROFILE table
|
||||
ArrayRef<Elf_CGProfile> CGProfile;
|
||||
|
||||
private:
|
||||
void
|
||||
initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups);
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# REQUIRES: x86
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||
|
||||
# RUN: ld.lld -e A %t -o /dev/null \
|
||||
# RUN: -noinhibit-exec -icf=all 2>&1 | FileCheck %s
|
||||
|
||||
.section .text.C,"ax",@progbits
|
||||
.globl C
|
||||
C:
|
||||
mov poppy, %rax
|
||||
retq
|
||||
|
||||
B = 0x1234
|
||||
|
||||
.section .text.A,"ax",@progbits
|
||||
.globl A
|
||||
A:
|
||||
mov poppy, %rax
|
||||
retq
|
||||
|
||||
.cg_profile A, B, 100
|
||||
.cg_profile A, C, 40
|
||||
.cg_profile B, C, 30
|
||||
.cg_profile adena1, A, 30
|
||||
.cg_profile A, adena2, 30
|
||||
.cg_profile poppy, A, 30
|
||||
|
||||
# CHECK: unable to order absolute symbol: B
|
||||
# CHECK: unable to order undefined symbol: adena1
|
||||
# CHECK: unable to order undefined symbol: adena2
|
||||
# CHECK: unable to order undefined symbol: poppy
|
||||
|
||||
# RUN: ld.lld %t -o /dev/null \
|
||||
# RUN: -noinhibit-exec -icf=all --no-warn-symbol-ordering 2>&1 \
|
||||
# RUN: | FileCheck %s --check-prefix=NOWARN
|
||||
# NOWARN-NOT: unable to order
|
|
@ -0,0 +1,41 @@
|
|||
# REQUIRES: x86
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
|
||||
# RUN: ld.lld -e A %t -o %t2
|
||||
# RUN: llvm-readobj -symbols %t2 | FileCheck %s
|
||||
|
||||
.section .text.D,"ax",@progbits
|
||||
D:
|
||||
retq
|
||||
|
||||
.section .text.C,"ax",@progbits
|
||||
.globl C
|
||||
C:
|
||||
retq
|
||||
|
||||
.section .text.B,"ax",@progbits
|
||||
.globl B
|
||||
B:
|
||||
retq
|
||||
|
||||
.section .text.A,"ax",@progbits
|
||||
.globl A
|
||||
A:
|
||||
Aa:
|
||||
retq
|
||||
|
||||
.cg_profile A, B, 10
|
||||
.cg_profile A, B, 10
|
||||
.cg_profile Aa, B, 80
|
||||
.cg_profile A, C, 40
|
||||
.cg_profile B, C, 30
|
||||
.cg_profile C, D, 90
|
||||
|
||||
# CHECK: Name: D
|
||||
# CHECK-NEXT: Value: 0x201003
|
||||
# CHECK: Name: A
|
||||
# CHECK-NEXT: Value: 0x201000
|
||||
# CHECK: Name: B
|
||||
# CHECK-NEXT: Value: 0x201001
|
||||
# CHECK: Name: C
|
||||
# CHECK-NEXT: Value: 0x201002
|
Loading…
Reference in New Issue