Skip to content

Commit 5c20143

Browse files
committed
[PseudoProbe] Support emitting to COFF object
Support emitting pseudo probe to .pseudo_probe and .pseudo_probe_desc COFF sections.
1 parent 7c53192 commit 5c20143

35 files changed

+363
-162
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1890,7 +1890,7 @@ defm pseudo_probe_for_profiling : BoolFOption<"pseudo-probe-for-profiling",
18901890
CodeGenOpts<"PseudoProbeForProfiling">, DefaultFalse,
18911891
PosFlag<SetTrue, [], [ClangOption], "Emit">,
18921892
NegFlag<SetFalse, [], [ClangOption], "Do not emit">,
1893-
BothFlags<[], [ClangOption, CC1Option],
1893+
BothFlags<[], [ClangOption, CC1Option, CLOption],
18941894
" pseudo probes for sample profiling">>;
18951895
def forder_file_instrumentation : Flag<["-"], "forder-file-instrumentation">,
18961896
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
@@ -720,6 +720,7 @@
720720
// RUN: -fno-profile-instr-use \
721721
// RUN: -fcs-profile-generate \
722722
// RUN: -fcs-profile-generate=dir \
723+
// RUN: -fpseudo-probe-for-profiling \
723724
// RUN: -ftime-trace \
724725
// RUN: -fmodules \
725726
// RUN: -fno-modules \

llvm/include/llvm/Target/TargetLoweringObjectFile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
9191
/// Emit Call Graph Profile metadata.
9292
void emitCGProfileMetadata(MCStreamer &Streamer, Module &M) const;
9393

94+
/// Emit pseudo_probe_desc metadata.
95+
void emitPseudoProbeDescMetadata(MCStreamer &Streamer, Module &M) const;
96+
9497
/// Get the module-level metadata that the platform cares about.
9598
virtual void getModuleMetadata(Module &M) {}
9699

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -335,28 +335,7 @@ void TargetLoweringObjectFileELF::emitModuleMetadata(MCStreamer &Streamer,
335335
}
336336
}
337337

338-
if (NamedMDNode *FuncInfo = M.getNamedMetadata(PseudoProbeDescMetadataName)) {
339-
// Emit a descriptor for every function including functions that have an
340-
// available external linkage. We may not want this for imported functions
341-
// that has code in another thinLTO module but we don't have a good way to
342-
// tell them apart from inline functions defined in header files. Therefore
343-
// we put each descriptor in a separate comdat section and rely on the
344-
// linker to deduplicate.
345-
for (const auto *Operand : FuncInfo->operands()) {
346-
const auto *MD = cast<MDNode>(Operand);
347-
auto *GUID = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0));
348-
auto *Hash = mdconst::dyn_extract<ConstantInt>(MD->getOperand(1));
349-
auto *Name = cast<MDString>(MD->getOperand(2));
350-
auto *S = C.getObjectFileInfo()->getPseudoProbeDescSection(
351-
TM->getFunctionSections() ? Name->getString() : StringRef());
352-
353-
Streamer.switchSection(S);
354-
Streamer.emitInt64(GUID->getZExtValue());
355-
Streamer.emitInt64(Hash->getZExtValue());
356-
Streamer.emitULEB128IntValue(Name->getString().size());
357-
Streamer.emitBytes(Name->getString());
358-
}
359-
}
338+
emitPseudoProbeDescMetadata(Streamer, M);
360339

361340
if (NamedMDNode *LLVMStats = M.getNamedMetadata("llvm.stats")) {
362341
// Emit the metadata for llvm statistics into .llvm_stats section, which is
@@ -1864,6 +1843,7 @@ void TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer,
18641843
}
18651844

18661845
emitCGProfileMetadata(Streamer, M);
1846+
emitPseudoProbeDescMetadata(Streamer, M);
18671847
}
18681848

18691849
void TargetLoweringObjectFileCOFF::emitLinkerDirectives(

llvm/lib/MC/MCAsmStreamer.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2492,7 +2492,8 @@ void MCAsmStreamer::emitPseudoProbe(uint64_t Guid, uint64_t Index,
24922492
for (const auto &Site : InlineStack)
24932493
OS << " @ " << std::get<0>(Site) << ":" << std::get<1>(Site);
24942494

2495-
OS << " " << FnSym->getName();
2495+
OS << " ";
2496+
FnSym->print(OS, MAI);
24962497

24972498
EmitEOL();
24982499
}

llvm/lib/MC/MCContext.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/MC/MCFragment.h"
2424
#include "llvm/MC/MCInst.h"
2525
#include "llvm/MC/MCLabel.h"
26+
#include "llvm/MC/MCObjectFileInfo.h"
2627
#include "llvm/MC/MCSectionCOFF.h"
2728
#include "llvm/MC/MCSectionDXContainer.h"
2829
#include "llvm/MC/MCSectionELF.h"
@@ -722,6 +723,13 @@ MCSectionCOFF *MCContext::getCOFFSection(StringRef Section,
722723
Iter->second = Result;
723724
auto *F = allocInitialFragment(*Result);
724725
Begin->setFragment(F);
726+
// Normally the comdat symbol is function begin label and will be set a
727+
// fragment in emitLabel. It is not hold for a pseudo_probe_desc comdat
728+
// symbol, so we need to set its fragment here.
729+
if (COMDATSymbol && !COMDATSymbol->getFragment() &&
730+
Section == MOFI->getPseudoProbeDescSection("")->getName()) {
731+
COMDATSymbol->setFragment(F);
732+
}
725733
return Result;
726734
}
727735

llvm/lib/MC/MCObjectFileInfo.cpp

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,16 @@ void MCObjectFileInfo::initCOFFMCObjectFileInfo(const Triple &T) {
792792
StackMapSection = Ctx->getCOFFSection(".llvm_stackmaps",
793793
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
794794
COFF::IMAGE_SCN_MEM_READ);
795+
796+
// Set IMAGE_SCN_MEM_DISCARDABLE so that lld will not truncate section name.
797+
PseudoProbeSection = Ctx->getCOFFSection(
798+
".pseudo_probe", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
799+
COFF::IMAGE_SCN_MEM_DISCARDABLE |
800+
COFF::IMAGE_SCN_MEM_READ);
801+
PseudoProbeDescSection = Ctx->getCOFFSection(
802+
".pseudo_probe_desc", COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
803+
COFF::IMAGE_SCN_MEM_DISCARDABLE |
804+
COFF::IMAGE_SCN_MEM_READ);
795805
}
796806

797807
void MCObjectFileInfo::initSPIRVMCObjectFileInfo(const Triple &T) {
@@ -1141,41 +1151,68 @@ MCObjectFileInfo::getKCFITrapSection(const MCSection &TextSec) const {
11411151

11421152
MCSection *
11431153
MCObjectFileInfo::getPseudoProbeSection(const MCSection &TextSec) const {
1144-
if (Ctx->getObjectFileType() != MCContext::IsELF)
1145-
return PseudoProbeSection;
1154+
auto ObjFileType = Ctx->getObjectFileType();
1155+
if (ObjFileType == MCContext::IsELF) {
1156+
const auto &ElfSec = static_cast<const MCSectionELF &>(TextSec);
1157+
unsigned Flags = ELF::SHF_LINK_ORDER;
1158+
StringRef GroupName;
1159+
if (const MCSymbol *Group = ElfSec.getGroup()) {
1160+
GroupName = Group->getName();
1161+
Flags |= ELF::SHF_GROUP;
1162+
}
11461163

1147-
const auto &ElfSec = static_cast<const MCSectionELF &>(TextSec);
1148-
unsigned Flags = ELF::SHF_LINK_ORDER;
1149-
StringRef GroupName;
1150-
if (const MCSymbol *Group = ElfSec.getGroup()) {
1151-
GroupName = Group->getName();
1152-
Flags |= ELF::SHF_GROUP;
1164+
return Ctx->getELFSection(PseudoProbeSection->getName(), ELF::SHT_PROGBITS,
1165+
Flags, 0, GroupName, true, ElfSec.getUniqueID(),
1166+
cast<MCSymbolELF>(TextSec.getBeginSymbol()));
1167+
} else if (ObjFileType == MCContext::IsCOFF) {
1168+
StringRef COMDATSymName = "";
1169+
int Selection = 0;
1170+
unsigned Characteristics =
1171+
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_DISCARDABLE |
1172+
COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_LNK_COMDAT;
1173+
auto &COFFSec = cast<MCSectionCOFF>(TextSec);
1174+
if (const MCSymbol *COMDATSym = COFFSec.getCOMDATSymbol()) {
1175+
// Associate .pseudo_probe to its function section.
1176+
COMDATSymName = COMDATSym->getName();
1177+
Selection = COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
1178+
}
1179+
1180+
return Ctx->getCOFFSection(PseudoProbeSection->getName(), Characteristics,
1181+
COMDATSymName, Selection, COFFSec.getUniqueID());
11531182
}
11541183

1155-
return Ctx->getELFSection(PseudoProbeSection->getName(), ELF::SHT_PROGBITS,
1156-
Flags, 0, GroupName, true, ElfSec.getUniqueID(),
1157-
cast<MCSymbolELF>(TextSec.getBeginSymbol()));
1184+
return PseudoProbeSection;
11581185
}
11591186

11601187
MCSection *
11611188
MCObjectFileInfo::getPseudoProbeDescSection(StringRef FuncName) const {
1162-
if (Ctx->getObjectFileType() == MCContext::IsELF) {
1163-
// Create a separate comdat group for each function's descriptor in order
1164-
// for the linker to deduplicate. The duplication, must be from different
1165-
// tranlation unit, can come from:
1166-
// 1. Inline functions defined in header files;
1167-
// 2. ThinLTO imported funcions;
1168-
// 3. Weak-linkage definitions.
1169-
// Use a concatenation of the section name and the function name as the
1170-
// group name so that descriptor-only groups won't be folded with groups of
1171-
// code.
1172-
if (Ctx->getTargetTriple().supportsCOMDAT() && !FuncName.empty()) {
1189+
// Create a separate comdat group for each function's descriptor in order
1190+
// for the linker to deduplicate. The duplication, must be from different
1191+
// tranlation unit, can come from:
1192+
// 1. Inline functions defined in header files;
1193+
// 2. ThinLTO imported funcions;
1194+
// 3. Weak-linkage definitions.
1195+
// Use a concatenation of the section name and the function name as the
1196+
// group name so that descriptor-only groups won't be folded with groups of
1197+
// code.
1198+
if (Ctx->getTargetTriple().supportsCOMDAT() && !FuncName.empty()) {
1199+
auto ObjFileType = Ctx->getObjectFileType();
1200+
if (ObjFileType == MCContext::IsELF) {
11731201
auto *S = static_cast<MCSectionELF *>(PseudoProbeDescSection);
11741202
auto Flags = S->getFlags() | ELF::SHF_GROUP;
11751203
return Ctx->getELFSection(S->getName(), S->getType(), Flags,
11761204
S->getEntrySize(),
11771205
S->getName() + "_" + FuncName,
11781206
/*IsComdat=*/true);
1207+
} else if (ObjFileType == MCContext::IsCOFF) {
1208+
unsigned Characteristics = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
1209+
COFF::IMAGE_SCN_MEM_DISCARDABLE |
1210+
COFF::IMAGE_SCN_MEM_READ |
1211+
COFF::IMAGE_SCN_LNK_COMDAT;
1212+
auto *S = cast<MCSectionCOFF>(PseudoProbeDescSection);
1213+
std::string COMDATSymName = (S->getName() + "_" + FuncName).str();
1214+
return Ctx->getCOFFSection(S->getName(), Characteristics, COMDATSymName,
1215+
COFF::IMAGE_COMDAT_SELECT_ANY);
11791216
}
11801217
}
11811218
return PseudoProbeDescSection;

llvm/lib/Target/TargetLoweringObjectFile.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,33 @@ void TargetLoweringObjectFile::emitCGProfileMetadata(MCStreamer &Streamer,
192192
}
193193
}
194194

195+
void TargetLoweringObjectFile::emitPseudoProbeDescMetadata(MCStreamer &Streamer,
196+
Module &M) const {
197+
if (NamedMDNode *FuncInfo = M.getNamedMetadata(PseudoProbeDescMetadataName)) {
198+
// Emit a descriptor for every function including functions that have an
199+
// available external linkage. We may not want this for imported functions
200+
// that has code in another thinLTO module but we don't have a good way to
201+
// tell them apart from inline functions defined in header files. Therefore
202+
// we put each descriptor in a separate comdat section and rely on the
203+
// linker to deduplicate.
204+
auto &C = getContext();
205+
for (const auto *Operand : FuncInfo->operands()) {
206+
const auto *MD = cast<MDNode>(Operand);
207+
auto *GUID = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0));
208+
auto *Hash = mdconst::dyn_extract<ConstantInt>(MD->getOperand(1));
209+
auto *Name = cast<MDString>(MD->getOperand(2));
210+
auto *S = C.getObjectFileInfo()->getPseudoProbeDescSection(
211+
TM->getFunctionSections() ? Name->getString() : StringRef());
212+
213+
Streamer.switchSection(S);
214+
Streamer.emitInt64(GUID->getZExtValue());
215+
Streamer.emitInt64(Hash->getZExtValue());
216+
Streamer.emitULEB128IntValue(Name->getString().size());
217+
Streamer.emitBytes(Name->getString());
218+
}
219+
}
220+
}
221+
195222
/// getKindForGlobal - This is a top-level target-independent classifier for
196223
/// a global object. Given a global variable and information from the TM, this
197224
/// function classifies the global in a target independent manner. This function

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; REQUIRES: x86_64-linux
1+
; REQUIRES: target={{x86_64-.*-(linux|windows).*}}
22
; REQUIRES: asserts
33
; 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 -S --debug-only=sample-profile,sample-profile-matcher,sample-profile-impl -pass-remarks=inline 2>&1 | FileCheck %s
44

@@ -14,7 +14,7 @@
1414

1515

1616
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"
17+
target triple = "x86_64-unknown--"
1818

1919
define available_externally i32 @main() #0 {
2020
%1 = call i32 @bar(), !dbg !13

llvm/test/Transforms/SampleProfile/pseudo-probe-dangle.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: target={{x86_64-.*-(linux|windows).*}}
22
; RUN: opt < %s -passes='pseudo-probe,jump-threading' -S -o %t
33
; RUN: FileCheck %s < %t --check-prefix=JT
44
; RUN: llc -function-sections <%t -filetype=asm | FileCheck %s --check-prefix=ASM

0 commit comments

Comments
 (0)