Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1851,7 +1851,7 @@ defm pseudo_probe_for_profiling
CodeGenOpts<"PseudoProbeForProfiling">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Emit">,
NegFlag<SetFalse, [], [ClangOption], "Do not emit">,
BothFlags<[], [ClangOption, CC1Option],
BothFlags<[], [ClangOption, CC1Option, CLOption],
" pseudo probes for sample profiling">>;
def fprofile_list_EQ : Joined<["-"], "fprofile-list=">,
Group<f_Group>, Visibility<[ClangOption, CC1Option, CLOption]>,
Expand Down
1 change: 1 addition & 0 deletions clang/test/Driver/cl-options.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,7 @@
// RUN: -fno-profile-instr-use \
// RUN: -fcs-profile-generate \
// RUN: -fcs-profile-generate=dir \
// RUN: -fpseudo-probe-for-profiling \
// RUN: -ftime-trace \
// RUN: -fmodules \
// RUN: -fno-modules \
Expand Down
4 changes: 3 additions & 1 deletion llvm/include/llvm/Target/TargetLoweringObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ class LLVM_ABI TargetLoweringObjectFile : public MCObjectFileInfo {
void emitCGProfileMetadata(MCStreamer &Streamer, Module &M) const;

/// Emit pseudo_probe_desc metadata.
void emitPseudoProbeDescMetadata(MCStreamer &Streamer, Module &M) const;
void emitPseudoProbeDescMetadata(MCStreamer &Streamer, Module &M,
std::function<void(MCStreamer &Streamer)>
COMDATSymEmitter = nullptr) const;

/// Process linker options metadata and emit platform-specific bits.
virtual void emitLinkerDirectives(MCStreamer &Streamer, Module &M) const {}
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1918,6 +1918,13 @@ void TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer,
}

emitCGProfileMetadata(Streamer, M);
emitPseudoProbeDescMetadata(Streamer, M, [](MCStreamer &Streamer) {
if (MCSymbol *Sym =
static_cast<MCSectionCOFF *>(Streamer.getCurrentSectionOnly())
->getCOMDATSymbol())
if (Sym->isUndefined())
Streamer.emitLabel(Sym);
});
}

void TargetLoweringObjectFileCOFF::emitLinkerDirectives(
Expand Down
96 changes: 65 additions & 31 deletions llvm/lib/MC/MCObjectFileInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,16 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
StackMapSection = Ctx->getCOFFSection(".llvm_stackmaps",
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ);

// Set IMAGE_SCN_MEM_DISCARDABLE so that lld will not truncate section name.
PseudoProbeSection = Ctx->getCOFFSection(
".pseudo_probe", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_DISCARDABLE |
COFF::IMAGE_SCN_MEM_READ);
PseudoProbeDescSection = Ctx->getCOFFSection(
".pseudo_probe_desc", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_DISCARDABLE |
COFF::IMAGE_SCN_MEM_READ);
}

void MCObjectFileInfo::initSPIRVMCObjectFileInfo(const Triple &T) {
Expand Down Expand Up @@ -1221,44 +1231,68 @@ MCObjectFileInfo::getKCFITrapSection(const MCSection &TextSec) const {

MCSection *
MCObjectFileInfo::getPseudoProbeSection(const MCSection &TextSec) const {
if (Ctx->getObjectFileType() != MCContext::IsELF)
return PseudoProbeSection;

const auto &ElfSec = static_cast<const MCSectionELF &>(TextSec);
unsigned Flags = ELF::SHF_LINK_ORDER;
StringRef GroupName;
if (const MCSymbol *Group = ElfSec.getGroup()) {
GroupName = Group->getName();
Flags |= ELF::SHF_GROUP;
auto ObjFileType = Ctx->getObjectFileType();
if (ObjFileType == MCContext::IsELF) {
const auto &ElfSec = static_cast<const MCSectionELF &>(TextSec);
unsigned Flags = ELF::SHF_LINK_ORDER;
StringRef GroupName;
if (const MCSymbol *Group = ElfSec.getGroup()) {
GroupName = Group->getName();
Flags |= ELF::SHF_GROUP;
}
return Ctx->getELFSection(
PseudoProbeSection->getName(), ELF::SHT_PROGBITS, Flags, 0, GroupName,
true, ElfSec.getUniqueID(),
static_cast<const MCSymbolELF *>(TextSec.getBeginSymbol()));
} else if (ObjFileType == MCContext::IsCOFF) {
StringRef COMDATSymName = "";
int Selection = 0;
unsigned Characteristics =
static_cast<MCSectionCOFF *>(PseudoProbeSection)->getCharacteristics();
const auto &COFFSec = static_cast<const MCSectionCOFF &>(TextSec);
if (const MCSymbol *COMDATSym = COFFSec.getCOMDATSymbol()) {
// Associate .pseudo_probe to its function section.
COMDATSymName = COMDATSym->getName();
Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
Selection = COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
}
return Ctx->getCOFFSection(PseudoProbeSection->getName(), Characteristics,
COMDATSymName, Selection, COFFSec.getUniqueID());
}

return Ctx->getELFSection(
PseudoProbeSection->getName(), ELF::SHT_PROGBITS, Flags, 0, GroupName,
true, ElfSec.getUniqueID(),
static_cast<const MCSymbolELF *>(TextSec.getBeginSymbol()));
return PseudoProbeSection;
}

MCSection *
MCObjectFileInfo::getPseudoProbeDescSection(StringRef FuncName) const {
if (Ctx->getObjectFileType() == MCContext::IsELF) {
// Create a separate comdat group for each function's descriptor in order
// for the linker to deduplicate. The duplication, must be from different
// tranlation unit, can come from:
// 1. Inline functions defined in header files;
// 2. ThinLTO imported funcions;
// 3. Weak-linkage definitions.
// Use a concatenation of the section name and the function name as the
// group name so that descriptor-only groups won't be folded with groups of
// code.
if (Ctx->getTargetTriple().supportsCOMDAT() && !FuncName.empty()) {
auto *S = static_cast<MCSectionELF *>(PseudoProbeDescSection);
auto Flags = S->getFlags() | ELF::SHF_GROUP;
return Ctx->getELFSection(S->getName(), S->getType(), Flags,
S->getEntrySize(),
S->getName() + "_" + FuncName,
/*IsComdat=*/true);
}
if (!Ctx->getTargetTriple().supportsCOMDAT() || FuncName.empty())
return PseudoProbeDescSection;

// Create a separate comdat group for each function's descriptor in order
// for the linker to deduplicate. The duplication, must be from different
// tranlation unit, can come from:
// 1. Inline functions defined in header files;
// 2. ThinLTO imported funcions;
// 3. Weak-linkage definitions.
// Use a concatenation of the section name and the function name as the
// group name so that descriptor-only groups won't be folded with groups of
// code.
auto ObjFileType = Ctx->getObjectFileType();
if (ObjFileType == MCContext::IsELF) {
auto *S = static_cast<MCSectionELF *>(PseudoProbeDescSection);
auto Flags = S->getFlags() | ELF::SHF_GROUP;
return Ctx->getELFSection(S->getName(), S->getType(), Flags,
S->getEntrySize(), S->getName() + "_" + FuncName,
/*IsComdat=*/true);
} else if (ObjFileType == MCContext::IsCOFF) {
auto *S = static_cast<MCSectionCOFF *>(PseudoProbeDescSection);
unsigned Characteristics =
S->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT;
std::string COMDATSymName = (S->getName() + "_" + FuncName).str();
return Ctx->getCOFFSection(S->getName(), Characteristics, COMDATSymName,
COFF::IMAGE_COMDAT_SELECT_ANY);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMAGE_COMDAT_SELECT_EXACT_MATCH?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good caught, it's possible that static function may have same function name.

}

return PseudoProbeDescSection;
}

Expand Down
10 changes: 8 additions & 2 deletions llvm/lib/Target/TargetLoweringObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,9 @@ void TargetLoweringObjectFile::emitCGProfileMetadata(MCStreamer &Streamer,
}
}

void TargetLoweringObjectFile::emitPseudoProbeDescMetadata(MCStreamer &Streamer,
Module &M) const {
void TargetLoweringObjectFile::emitPseudoProbeDescMetadata(
MCStreamer &Streamer, Module &M,
std::function<void(MCStreamer &Streamer)> COMDATSymEmitter) const {
NamedMDNode *FuncInfo = M.getNamedMetadata(PseudoProbeDescMetadataName);
if (!FuncInfo)
return;
Expand All @@ -213,6 +214,11 @@ void TargetLoweringObjectFile::emitPseudoProbeDescMetadata(MCStreamer &Streamer,
TM->getFunctionSections() ? Name->getString() : StringRef());

Streamer.switchSection(S);

// emit COFF COMDAT symbol.
if (COMDATSymEmitter)
COMDATSymEmitter(Streamer);

Streamer.emitInt64(GUID->getZExtValue());
Streamer.emitInt64(Hash->getZExtValue());
Streamer.emitULEB128IntValue(Name->getString().size());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
; REQUIRES: x86_64-linux
; REQUIRES: asserts
; REQUIRES: asserts && x86-registered-target
; RUN: opt < %s -passes='thinlto<O2>' -pgo-kind=pgo-sample-use-pipeline -sample-profile-file=%S/Inputs/pseudo-probe-callee-profile-mismatch.prof --salvage-stale-profile --salvage-unused-profile=false -S --debug-only=sample-profile,sample-profile-matcher,sample-profile-impl -pass-remarks=inline 2>&1 | FileCheck %s

; There is no profile-checksum-mismatch attr, even the checksum is mismatched in the pseudo_probe_desc, it doesn't run the matching.
Expand All @@ -13,9 +12,6 @@
; CHECK: Profile is invalid due to CFG mismatch for Function bar


target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define available_externally i32 @main() #0 {
%1 = call i32 @bar(), !dbg !13
ret i32 0
Expand Down
7 changes: 4 additions & 3 deletions llvm/test/Transforms/SampleProfile/pseudo-probe-dangle.ll
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
; REQUIRES: x86_64-linux
; REQUIRES: x86-registered-target
; RUN: opt < %s -passes='pseudo-probe,jump-threading' -S -o %t
; RUN: FileCheck %s < %t --check-prefix=JT
; RUN: llc -function-sections <%t -filetype=asm | FileCheck %s --check-prefix=ASM
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -function-sections <%t -filetype=asm | FileCheck %s --check-prefix=ASM
; RUN: llc -mtriple=x86_64-unknown-windows-msvc -function-sections <%t -filetype=asm | FileCheck %s --check-prefix=ASM
; RUN: opt < %s -passes='pseudo-probe' -S -o %t1
; RUN: llc -stop-after=tailduplication <%t1 | FileCheck %s --check-prefix=MIR-tail
; RUN: llc -stop-after=tailduplication <%t1 | FileCheck %s --check-prefix=MIR-tail
; RUN: opt < %s -passes='pseudo-probe,simplifycfg' -S | FileCheck %s --check-prefix=SC

declare i32 @f1()
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/SampleProfile/pseudo-probe-dangle2.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; REQUIRES: x86_64-linux
; REQUIRES: x86-registered-target
; RUN: opt < %s -passes=simplifycfg -S -o %t
; RUN: FileCheck %s < %t

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; REQUIRES: x86_64-linux
; REQUIRES: x86-registered-target
; RUN: opt < %s -passes=pseudo-probe -S -o - | FileCheck %s

; CHECK: ![[#]] = !{i64 -3345296970173352005, i64 [[#]], !"foo.dbg"}
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Transforms/SampleProfile/pseudo-probe-eh.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; REQUIRES: x86_64-linux
; REQUIRES: x86-registered-target
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lit case is Linux specific.

; RUN: opt < %s -passes=pseudo-probe -function-sections -S -o - | FileCheck %s

;; Check the generation of pseudoprobe intrinsic call for non-EH blocks only.
Expand Down
78 changes: 53 additions & 25 deletions llvm/test/Transforms/SampleProfile/pseudo-probe-emit-inline.ll
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
; REQUIRES: x86_64-linux
; RUN: opt < %s -passes='pseudo-probe,cgscc(inline)' -function-sections -mtriple=x86_64-unknown-linux-gnu -S -o %t
; REQUIRES: x86-registered-target
; RUN: opt < %s -passes='pseudo-probe,cgscc(inline)' -function-sections -S -o %t
; RUN: FileCheck %s < %t --check-prefix=CHECK-IL
; RUN: llc -function-sections <%t -filetype=asm -o %t1
; RUN: FileCheck %s < %t1 --check-prefix=CHECK-ASM
; RUN: llc -function-sections <%t -filetype=obj -o %t2
; RUN: llvm-objdump --section-headers %t2 | FileCheck %s --check-prefix=CHECK-OBJ
; RUN: llvm-mc -filetype=asm <%t1 -o %t3
; RUN: FileCheck %s < %t3 --check-prefix=CHECK-ASM
; RUN: llvm-mc -filetype=obj <%t1 -o %t4
; RUN: llvm-objdump --section-headers %t4 | FileCheck %s --check-prefix=CHECK-OBJ
; For ELF.
; RUN: llc -function-sections -mtriple=x86_64-unknown-linux-gnu <%t -filetype=asm -o %t1
; RUN: FileCheck %s < %t1 --check-prefixes=CHECK-ASM,CHECK-ASM-ELF
; RUN: llc -function-sections -mtriple=x86_64-unknown-linux-gnu <%t -filetype=obj -o %t2
; RUN: llvm-objdump --section-headers %t2 | FileCheck %s --check-prefix=CHECK-OBJ
; RUN: llvm-mc -triple=x86_64-unknown-linux-gnu -filetype=asm <%t1 -o %t3
; RUN: FileCheck %s < %t3 --check-prefixes=CHECK-ASM,CHECK-ASM-ELF
; RUN: llvm-mc -triple=x86_64-unknown-linux-gnu -filetype=obj <%t1 -o %t4
; RUN: llvm-objdump --section-headers %t4 | FileCheck %s --check-prefix=CHECK-OBJ
; For COFF.
; RUN: llc -function-sections -mtriple=x86_64-unknown-windows-msvc <%t -filetype=asm -o %t1
; RUN: FileCheck %s < %t1 --check-prefixes=CHECK-ASM,CHECK-ASM-COFF
; RUN: llc -function-sections -mtriple=x86_64-unknown-windows-msvc <%t -filetype=obj -o %t2
; RUN: llvm-objdump --section-headers %t2 | FileCheck %s --check-prefixes=CHECK-OBJ
; RUN: llvm-mc -triple=x86_64-unknown-windows-msvc -filetype=asm <%t1 -o %t3
; RUN: FileCheck %s < %t3 --check-prefixes=CHECK-ASM,CHECK-ASM-COFF
; RUN: llvm-mc -triple=x86_64-unknown-windows-msvc -filetype=obj <%t1 -o %t4
; RUN: llvm-objdump --section-headers %t4 | FileCheck %s --check-prefixes=CHECK-OBJ


define dso_local void @foo2() !dbg !7 {
Expand Down Expand Up @@ -54,21 +64,39 @@ define dso_local i32 @entry() !dbg !14 {


; Check the generation of .pseudo_probe_desc section
; CHECK-ASM: .section .pseudo_probe_desc,"G",@progbits,.pseudo_probe_desc_foo2,comdat
; CHECK-ASM-NEXT: .quad [[#GUID1]]
; CHECK-ASM-NEXT: .quad [[#HASH1:]]
; CHECK-ASM-NEXT: .byte 4
; CHECK-ASM-NEXT: .ascii "foo2"
; CHECK-ASM-NEXT: .section .pseudo_probe_desc,"G",@progbits,.pseudo_probe_desc_foo,comdat
; CHECK-ASM-NEXT: .quad [[#GUID2]]
; CHECK-ASM-NEXT: .quad [[#HASH2:]]
; CHECK-ASM-NEXT: .byte 3
; CHECK-ASM-NEXT: .ascii "foo"
; CHECK-ASM-NEXT: .section .pseudo_probe_desc,"G",@progbits,.pseudo_probe_desc_entry,comdat
; CHECK-ASM-NEXT: .quad [[#GUID3]]
; CHECK-ASM-NEXT: .quad [[#HASH3:]]
; CHECK-ASM-NEXT: .byte 5
; CHECK-ASM-NEXT: .ascii "entry"
; CHECK-ASM-ELF: .section .pseudo_probe_desc,"G",@progbits,.pseudo_probe_desc_foo2,comdat
; CHECK-ASM-ELF-NEXT: .quad [[#GUID1]]
; CHECK-ASM-ELF-NEXT: .quad [[#HASH1:]]
; CHECK-ASM-ELF-NEXT: .byte 4
; CHECK-ASM-ELF-NEXT: .ascii "foo2"
; CHECK-ASM-ELF-NEXT: .section .pseudo_probe_desc,"G",@progbits,.pseudo_probe_desc_foo,comdat
; CHECK-ASM-ELF-NEXT: .quad [[#GUID2]]
; CHECK-ASM-ELF-NEXT: .quad [[#HASH2:]]
; CHECK-ASM-ELF-NEXT: .byte 3
; CHECK-ASM-ELF-NEXT: .ascii "foo"
; CHECK-ASM-ELF-NEXT: .section .pseudo_probe_desc,"G",@progbits,.pseudo_probe_desc_entry,comdat
; CHECK-ASM-ELF-NEXT: .quad [[#GUID3]]
; CHECK-ASM-ELF-NEXT: .quad [[#HASH3:]]
; CHECK-ASM-ELF-NEXT: .byte 5
; CHECK-ASM-ELF-NEXT: .ascii "entry"
; CHECK-ASM-COFF: .section .pseudo_probe_desc,"drD",discard,.pseudo_probe_desc_foo2
; CHECK-ASM-COFF-NEXT: .pseudo_probe_desc_foo2:
; CHECK-ASM-COFF-NEXT: .quad [[#GUID1]]
; CHECK-ASM-COFF-NEXT: .quad [[#HASH1:]]
; CHECK-ASM-COFF-NEXT: .byte 4
; CHECK-ASM-COFF-NEXT: .ascii "foo2"
; CHECK-ASM-COFF-NEXT: .section .pseudo_probe_desc,"drD",discard,.pseudo_probe_desc_foo
; CHECK-ASM-COFF: .pseudo_probe_desc_foo:
; CHECK-ASM-COFF-NEXT: .quad [[#GUID2]]
; CHECK-ASM-COFF-NEXT: .quad [[#HASH2:]]
; CHECK-ASM-COFF-NEXT: .byte 3
; CHECK-ASM-COFF-NEXT: .ascii "foo"
; CHECK-ASM-COFF-NEXT: .section .pseudo_probe_desc,"drD",discard,.pseudo_probe_desc_entry
; CHECK-ASM-COFF: .pseudo_probe_desc_entry:
; CHECK-ASM-COFF-NEXT: .quad [[#GUID3]]
; CHECK-ASM-COFF-NEXT: .quad [[#HASH3:]]
; CHECK-ASM-COFF-NEXT: .byte 5
; CHECK-ASM-COFF-NEXT: .ascii "entry"

; CHECK-OBJ: .pseudo_probe_desc
; CHECK-OBJ: .pseudo_probe
Expand Down
Loading
Loading