Skip to content

Commit 2e12299

Browse files
authored
[PseudoProbe] Support emitting to COFF object (#123870)
RFC: https://discourse.llvm.org/t/rfc-support-pseudo-probe-for-windows-coff/83820 Support emitting pseudo probe to .pseudo_probe and .pseudo_probe_desc COFF sections.
1 parent a49030e commit 2e12299

30 files changed

+335
-184
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1851,7 +1851,7 @@ defm pseudo_probe_for_profiling
18511851
CodeGenOpts<"PseudoProbeForProfiling">, DefaultFalse,
18521852
PosFlag<SetTrue, [], [ClangOption], "Emit">,
18531853
NegFlag<SetFalse, [], [ClangOption], "Do not emit">,
1854-
BothFlags<[], [ClangOption, CC1Option],
1854+
BothFlags<[], [ClangOption, CC1Option, CLOption],
18551855
" pseudo probes for sample profiling">>;
18561856
def fprofile_list_EQ : Joined<["-"], "fprofile-list=">,
18571857
Group<f_Group>, Visibility<[ClangOption, CC1Option, CLOption]>,

clang/test/Driver/cl-options.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,7 @@
728728
// RUN: -fno-profile-instr-use \
729729
// RUN: -fcs-profile-generate \
730730
// RUN: -fcs-profile-generate=dir \
731+
// RUN: -fpseudo-probe-for-profiling \
731732
// RUN: -ftime-trace \
732733
// RUN: -fmodules \
733734
// RUN: -fno-modules \

llvm/include/llvm/Target/TargetLoweringObjectFile.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ class LLVM_ABI TargetLoweringObjectFile : public MCObjectFileInfo {
9494
void emitCGProfileMetadata(MCStreamer &Streamer, Module &M) const;
9595

9696
/// Emit pseudo_probe_desc metadata.
97-
void emitPseudoProbeDescMetadata(MCStreamer &Streamer, Module &M) const;
97+
void emitPseudoProbeDescMetadata(MCStreamer &Streamer, Module &M,
98+
std::function<void(MCStreamer &Streamer)>
99+
COMDATSymEmitter = nullptr) const;
98100

99101
/// Process linker options metadata and emit platform-specific bits.
100102
virtual void emitLinkerDirectives(MCStreamer &Streamer, Module &M) const {}

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1920,6 +1920,13 @@ void TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer,
19201920
}
19211921

19221922
emitCGProfileMetadata(Streamer, M);
1923+
emitPseudoProbeDescMetadata(Streamer, M, [](MCStreamer &Streamer) {
1924+
if (MCSymbol *Sym =
1925+
static_cast<MCSectionCOFF *>(Streamer.getCurrentSectionOnly())
1926+
->getCOMDATSymbol())
1927+
if (Sym->isUndefined())
1928+
Streamer.emitLabel(Sym);
1929+
});
19231930
}
19241931

19251932
void TargetLoweringObjectFileCOFF::emitLinkerDirectives(

llvm/lib/MC/MCObjectFileInfo.cpp

Lines changed: 65 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,16 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
849849
StackMapSection = Ctx->getCOFFSection(".llvm_stackmaps",
850850
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
851851
COFF::IMAGE_SCN_MEM_READ);
852+
853+
// Set IMAGE_SCN_MEM_DISCARDABLE so that lld will not truncate section name.
854+
PseudoProbeSection = Ctx->getCOFFSection(
855+
".pseudo_probe", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
856+
COFF::IMAGE_SCN_MEM_DISCARDABLE |
857+
COFF::IMAGE_SCN_MEM_READ);
858+
PseudoProbeDescSection = Ctx->getCOFFSection(
859+
".pseudo_probe_desc", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
860+
COFF::IMAGE_SCN_MEM_DISCARDABLE |
861+
COFF::IMAGE_SCN_MEM_READ);
852862
}
853863

854864
void MCObjectFileInfo::initSPIRVMCObjectFileInfo(const Triple &T) {
@@ -1220,44 +1230,68 @@ MCObjectFileInfo::getKCFITrapSection(const MCSection &TextSec) const {
12201230

12211231
MCSection *
12221232
MCObjectFileInfo::getPseudoProbeSection(const MCSection &TextSec) const {
1223-
if (Ctx->getObjectFileType() != MCContext::IsELF)
1224-
return PseudoProbeSection;
1225-
1226-
const auto &ElfSec = static_cast<const MCSectionELF &>(TextSec);
1227-
unsigned Flags = ELF::SHF_LINK_ORDER;
1228-
StringRef GroupName;
1229-
if (const MCSymbol *Group = ElfSec.getGroup()) {
1230-
GroupName = Group->getName();
1231-
Flags |= ELF::SHF_GROUP;
1233+
auto ObjFileType = Ctx->getObjectFileType();
1234+
if (ObjFileType == MCContext::IsELF) {
1235+
const auto &ElfSec = static_cast<const MCSectionELF &>(TextSec);
1236+
unsigned Flags = ELF::SHF_LINK_ORDER;
1237+
StringRef GroupName;
1238+
if (const MCSymbol *Group = ElfSec.getGroup()) {
1239+
GroupName = Group->getName();
1240+
Flags |= ELF::SHF_GROUP;
1241+
}
1242+
return Ctx->getELFSection(
1243+
PseudoProbeSection->getName(), ELF::SHT_PROGBITS, Flags, 0, GroupName,
1244+
true, ElfSec.getUniqueID(),
1245+
static_cast<const MCSymbolELF *>(TextSec.getBeginSymbol()));
1246+
} else if (ObjFileType == MCContext::IsCOFF) {
1247+
StringRef COMDATSymName = "";
1248+
int Selection = 0;
1249+
unsigned Characteristics =
1250+
static_cast<MCSectionCOFF *>(PseudoProbeSection)->getCharacteristics();
1251+
const auto &COFFSec = static_cast<const MCSectionCOFF &>(TextSec);
1252+
if (const MCSymbol *COMDATSym = COFFSec.getCOMDATSymbol()) {
1253+
// Associate .pseudo_probe to its function section.
1254+
COMDATSymName = COMDATSym->getName();
1255+
Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
1256+
Selection = COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
1257+
}
1258+
return Ctx->getCOFFSection(PseudoProbeSection->getName(), Characteristics,
1259+
COMDATSymName, Selection, COFFSec.getUniqueID());
12321260
}
12331261

1234-
return Ctx->getELFSection(
1235-
PseudoProbeSection->getName(), ELF::SHT_PROGBITS, Flags, 0, GroupName,
1236-
true, ElfSec.getUniqueID(),
1237-
static_cast<const MCSymbolELF *>(TextSec.getBeginSymbol()));
1262+
return PseudoProbeSection;
12381263
}
12391264

12401265
MCSection *
12411266
MCObjectFileInfo::getPseudoProbeDescSection(StringRef FuncName) const {
1242-
if (Ctx->getObjectFileType() == MCContext::IsELF) {
1243-
// Create a separate comdat group for each function's descriptor in order
1244-
// for the linker to deduplicate. The duplication, must be from different
1245-
// tranlation unit, can come from:
1246-
// 1. Inline functions defined in header files;
1247-
// 2. ThinLTO imported funcions;
1248-
// 3. Weak-linkage definitions.
1249-
// Use a concatenation of the section name and the function name as the
1250-
// group name so that descriptor-only groups won't be folded with groups of
1251-
// code.
1252-
if (Ctx->getTargetTriple().supportsCOMDAT() && !FuncName.empty()) {
1253-
auto *S = static_cast<MCSectionELF *>(PseudoProbeDescSection);
1254-
auto Flags = S->getFlags() | ELF::SHF_GROUP;
1255-
return Ctx->getELFSection(S->getName(), S->getType(), Flags,
1256-
S->getEntrySize(),
1257-
S->getName() + "_" + FuncName,
1258-
/*IsComdat=*/true);
1259-
}
1267+
if (!Ctx->getTargetTriple().supportsCOMDAT() || FuncName.empty())
1268+
return PseudoProbeDescSection;
1269+
1270+
// Create a separate comdat group for each function's descriptor in order
1271+
// for the linker to deduplicate. The duplication, must be from different
1272+
// tranlation unit, can come from:
1273+
// 1. Inline functions defined in header files;
1274+
// 2. ThinLTO imported funcions;
1275+
// 3. Weak-linkage definitions.
1276+
// Use a concatenation of the section name and the function name as the
1277+
// group name so that descriptor-only groups won't be folded with groups of
1278+
// code.
1279+
auto ObjFileType = Ctx->getObjectFileType();
1280+
if (ObjFileType == MCContext::IsELF) {
1281+
auto *S = static_cast<MCSectionELF *>(PseudoProbeDescSection);
1282+
auto Flags = S->getFlags() | ELF::SHF_GROUP;
1283+
return Ctx->getELFSection(S->getName(), S->getType(), Flags,
1284+
S->getEntrySize(), S->getName() + "_" + FuncName,
1285+
/*IsComdat=*/true);
1286+
} else if (ObjFileType == MCContext::IsCOFF) {
1287+
auto *S = static_cast<MCSectionCOFF *>(PseudoProbeDescSection);
1288+
unsigned Characteristics =
1289+
S->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT;
1290+
std::string COMDATSymName = (S->getName() + "_" + FuncName).str();
1291+
return Ctx->getCOFFSection(S->getName(), Characteristics, COMDATSymName,
1292+
COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH);
12601293
}
1294+
12611295
return PseudoProbeDescSection;
12621296
}
12631297

llvm/lib/Target/TargetLoweringObjectFile.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,9 @@ void TargetLoweringObjectFile::emitCGProfileMetadata(MCStreamer &Streamer,
191191
}
192192
}
193193

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

215216
Streamer.switchSection(S);
217+
218+
// emit COFF COMDAT symbol.
219+
if (COMDATSymEmitter)
220+
COMDATSymEmitter(Streamer);
221+
216222
Streamer.emitInt64(GUID->getZExtValue());
217223
Streamer.emitInt64(Hash->getZExtValue());
218224
Streamer.emitULEB128IntValue(Name->getString().size());

llvm/test/Transforms/SampleProfile/pseudo-probe-callee-profile-mismatch.ll

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
; REQUIRES: x86_64-linux
2-
; REQUIRES: asserts
1+
; REQUIRES: asserts && x86-registered-target
32
; 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
43

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

1514

16-
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"
17-
target triple = "x86_64-unknown-linux-gnu"
18-
1915
define available_externally i32 @main() #0 {
2016
%1 = call i32 @bar(), !dbg !13
2117
ret i32 0

llvm/test/Transforms/SampleProfile/pseudo-probe-dangle.ll

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
; REQUIRES: x86_64-linux
1+
; REQUIRES: x86-registered-target
22
; RUN: opt < %s -passes='pseudo-probe,jump-threading' -S -o %t
33
; RUN: FileCheck %s < %t --check-prefix=JT
4-
; RUN: llc -function-sections <%t -filetype=asm | FileCheck %s --check-prefix=ASM
4+
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -function-sections <%t -filetype=asm | FileCheck %s --check-prefix=ASM
5+
; RUN: llc -mtriple=x86_64-unknown-windows-msvc -function-sections <%t -filetype=asm | FileCheck %s --check-prefix=ASM
56
; RUN: opt < %s -passes='pseudo-probe' -S -o %t1
6-
; RUN: llc -stop-after=tailduplication <%t1 | FileCheck %s --check-prefix=MIR-tail
7+
; RUN: llc -mtriple=x86_64-- -stop-after=tailduplication <%t1 | FileCheck %s --check-prefix=MIR-tail
78
; RUN: opt < %s -passes='pseudo-probe,simplifycfg' -S | FileCheck %s --check-prefix=SC
89

910
declare i32 @f1()

llvm/test/Transforms/SampleProfile/pseudo-probe-dangle2.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; REQUIRES: x86_64-linux
1+
; REQUIRES: x86-registered-target
22
; RUN: opt < %s -passes=simplifycfg -S -o %t
33
; RUN: FileCheck %s < %t
44

llvm/test/Transforms/SampleProfile/pseudo-probe-desc-guid.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; REQUIRES: x86_64-linux
1+
; REQUIRES: x86-registered-target
22
; RUN: opt < %s -passes=pseudo-probe -S -o - | FileCheck %s
33

44
; CHECK: ![[#]] = !{i64 -3345296970173352005, i64 [[#]], !"foo.dbg"}

0 commit comments

Comments
 (0)