Skip to content

Commit a2a6f9f

Browse files
[AsmPrinter][TargetLowering]Place a hot jump table into a hot-suffixed section
1 parent 5d207e9 commit a2a6f9f

File tree

8 files changed

+130
-38
lines changed

8 files changed

+130
-38
lines changed

llvm/include/llvm/CodeGen/AsmPrinter.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,10 @@ class AsmPrinter : public MachineFunctionPass {
453453
/// function to the current output stream.
454454
virtual void emitJumpTableInfo();
455455

456+
virtual void emitJumpTables(const std::vector<unsigned> &JumpTableIndices,
457+
MCSection *JumpTableSection, bool JTInDiffSection,
458+
const MachineJumpTableInfo &MJTI);
459+
456460
/// Emit the specified global variable to the .s file.
457461
virtual void emitGlobalVariable(const GlobalVariable *GV);
458462

@@ -892,10 +896,10 @@ class AsmPrinter : public MachineFunctionPass {
892896
// Internal Implementation Details
893897
//===------------------------------------------------------------------===//
894898

895-
void emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
899+
void emitJumpTableEntry(const MachineJumpTableInfo &MJTI,
896900
const MachineBasicBlock *MBB, unsigned uid) const;
897901

898-
void emitJumpTableSizesSection(const MachineJumpTableInfo *MJTI,
902+
void emitJumpTableSizesSection(const MachineJumpTableInfo &MJTI,
899903
const Function &F) const;
900904

901905
void emitLLVMUsedList(const ConstantArray *InitList);

llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
7474

7575
MCSection *getSectionForJumpTable(const Function &F,
7676
const TargetMachine &TM) const override;
77+
MCSection *
78+
getSectionForJumpTable(const Function &F, const TargetMachine &TM,
79+
const MachineJumpTableEntry *JTE) const override;
7780
MCSection *getSectionForLSDA(const Function &F, const MCSymbol &FnSym,
7881
const TargetMachine &TM) const override;
7982

llvm/include/llvm/Target/TargetLoweringObjectFile.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class Function;
2727
class GlobalObject;
2828
class GlobalValue;
2929
class MachineBasicBlock;
30+
class MachineJumpTableEntry;
3031
class MachineModuleInfo;
3132
class Mangler;
3233
class MCContext;
@@ -132,6 +133,10 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
132133

133134
virtual MCSection *getSectionForJumpTable(const Function &F,
134135
const TargetMachine &TM) const;
136+
virtual MCSection *
137+
getSectionForJumpTable(const Function &F, const TargetMachine &TM,
138+
const MachineJumpTableEntry *JTE) const;
139+
135140
virtual MCSection *getSectionForLSDA(const Function &, const MCSymbol &,
136141
const TargetMachine &) const {
137142
return LSDASection;

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 76 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ static cl::opt<bool> BBAddrMapSkipEmitBBEntries(
168168
"unnecessary for some PGOAnalysisMap features."),
169169
cl::Hidden, cl::init(false));
170170

171+
static cl::opt<bool>
172+
EmitStaticDataHotnessSuffix("emit-static-data-hotness-suffix", cl::Hidden,
173+
cl::init(false), cl::ZeroOrMore,
174+
cl::desc("Emit static data hotness suffix"));
175+
171176
static cl::opt<bool> EmitJumpTableSizesSection(
172177
"emit-jump-table-sizes-section",
173178
cl::desc("Emit a section containing jump table addresses and sizes"),
@@ -2861,7 +2866,6 @@ void AsmPrinter::emitConstantPool() {
28612866
// Print assembly representations of the jump tables used by the current
28622867
// function.
28632868
void AsmPrinter::emitJumpTableInfo() {
2864-
const DataLayout &DL = MF->getDataLayout();
28652869
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
28662870
if (!MJTI) return;
28672871
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return;
@@ -2876,42 +2880,88 @@ void AsmPrinter::emitJumpTableInfo() {
28762880
MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 ||
28772881
MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference64,
28782882
F);
2883+
2884+
if (!EmitStaticDataHotnessSuffix) {
2885+
std::vector<unsigned> JumpTableIndices;
2886+
for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI)
2887+
JumpTableIndices.push_back(JTI);
2888+
// Prior code in this function verifies JT is not empty. Use JT[0] directly.
2889+
emitJumpTables(JumpTableIndices, TLOF.getSectionForJumpTable(F, TM),
2890+
JTInDiffSection, *MJTI);
2891+
return;
2892+
}
2893+
2894+
// Iterate all jump tables, put them into two vectors, hot and lukewarm
2895+
std::vector<unsigned> HotOrWarmJumpTableIndices, ColdJumpTableIndices;
2896+
2897+
for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
2898+
if (JT[JTI].Hotness == llvm::DataHotness::Cold)
2899+
ColdJumpTableIndices.push_back(JTI);
2900+
else
2901+
HotOrWarmJumpTableIndices.push_back(JTI);
2902+
}
2903+
2904+
if (!HotOrWarmJumpTableIndices.empty())
2905+
emitJumpTables(HotOrWarmJumpTableIndices,
2906+
TLOF.getSectionForJumpTable(
2907+
F, TM, &JT[*HotOrWarmJumpTableIndices.begin()]),
2908+
JTInDiffSection, *MJTI);
2909+
2910+
if (!ColdJumpTableIndices.empty())
2911+
emitJumpTables(
2912+
ColdJumpTableIndices,
2913+
TLOF.getSectionForJumpTable(F, TM, &JT[*ColdJumpTableIndices.begin()]),
2914+
JTInDiffSection, *MJTI);
2915+
2916+
return;
2917+
}
2918+
2919+
void AsmPrinter::emitJumpTables(const std::vector<unsigned> &JumpTableIndices,
2920+
MCSection *JumpTableSection,
2921+
bool JTInDiffSection,
2922+
const MachineJumpTableInfo &MJTI) {
2923+
if (JumpTableIndices.empty())
2924+
return;
2925+
2926+
const DataLayout &DL = MF->getDataLayout();
28792927
if (JTInDiffSection) {
2880-
// Drop it in the readonly section.
2881-
MCSection *ReadOnlySection = TLOF.getSectionForJumpTable(F, TM);
2882-
OutStreamer->switchSection(ReadOnlySection);
2928+
OutStreamer->switchSection(JumpTableSection);
28832929
}
28842930

2885-
emitAlignment(Align(MJTI->getEntryAlignment(DL)));
2931+
emitAlignment(Align(MJTI.getEntryAlignment(MF->getDataLayout())));
28862932

28872933
// Jump tables in code sections are marked with a data_region directive
28882934
// where that's supported.
28892935
if (!JTInDiffSection)
28902936
OutStreamer->emitDataRegion(MCDR_DataRegionJT32);
28912937

2892-
for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
2893-
const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
2938+
const auto &JT = MJTI.getJumpTables();
2939+
for (unsigned Index = 0, e = JumpTableIndices.size(); Index != e; ++Index) {
2940+
const std::vector<MachineBasicBlock *> &JTBBs =
2941+
JT[JumpTableIndices[Index]].MBBs;
28942942

28952943
// If this jump table was deleted, ignore it.
2896-
if (JTBBs.empty()) continue;
2944+
if (JTBBs.empty())
2945+
continue;
28972946

28982947
// For the EK_LabelDifference32 entry, if using .set avoids a relocation,
28992948
/// emit a .set directive for each unique entry.
2900-
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
2949+
if (MJTI.getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
29012950
MAI->doesSetDirectiveSuppressReloc()) {
2902-
SmallPtrSet<const MachineBasicBlock*, 16> EmittedSets;
2951+
SmallPtrSet<const MachineBasicBlock *, 16> EmittedSets;
29032952
const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
2904-
const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF,JTI,OutContext);
2953+
const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(
2954+
MF, JumpTableIndices[Index], OutContext);
29052955
for (const MachineBasicBlock *MBB : JTBBs) {
29062956
if (!EmittedSets.insert(MBB).second)
29072957
continue;
29082958

29092959
// .set LJTSet, LBB32-base
29102960
const MCExpr *LHS =
2911-
MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
2912-
OutStreamer->emitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()),
2913-
MCBinaryExpr::createSub(LHS, Base,
2914-
OutContext));
2961+
MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
2962+
OutStreamer->emitAssignment(
2963+
GetJTSetSymbol(JumpTableIndices[Index], MBB->getNumber()),
2964+
MCBinaryExpr::createSub(LHS, Base, OutContext));
29152965
}
29162966
}
29172967

@@ -2923,27 +2973,27 @@ void AsmPrinter::emitJumpTableInfo() {
29232973
// FIXME: This doesn't have to have any specific name, just any randomly
29242974
// named and numbered local label started with 'l' would work. Simplify
29252975
// GetJTISymbol.
2926-
OutStreamer->emitLabel(GetJTISymbol(JTI, true));
2976+
OutStreamer->emitLabel(GetJTISymbol(JumpTableIndices[Index], true));
29272977

2928-
MCSymbol* JTISymbol = GetJTISymbol(JTI);
2978+
MCSymbol *JTISymbol = GetJTISymbol(JumpTableIndices[Index]);
29292979
OutStreamer->emitLabel(JTISymbol);
29302980

29312981
// Defer MCAssembler based constant folding due to a performance issue. The
29322982
// label differences will be evaluated at write time.
29332983
for (const MachineBasicBlock *MBB : JTBBs)
2934-
emitJumpTableEntry(MJTI, MBB, JTI);
2984+
emitJumpTableEntry(MJTI, MBB, JumpTableIndices[Index]);
29352985
}
29362986

29372987
if (EmitJumpTableSizesSection)
2938-
emitJumpTableSizesSection(MJTI, F);
2988+
emitJumpTableSizesSection(MJTI, MF->getFunction());
29392989

29402990
if (!JTInDiffSection)
29412991
OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
29422992
}
29432993

2944-
void AsmPrinter::emitJumpTableSizesSection(const MachineJumpTableInfo *MJTI,
2994+
void AsmPrinter::emitJumpTableSizesSection(const MachineJumpTableInfo &MJTI,
29452995
const Function &F) const {
2946-
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
2996+
const std::vector<MachineJumpTableEntry> &JT = MJTI.getJumpTables();
29472997

29482998
if (JT.empty())
29492999
return;
@@ -2991,17 +3041,17 @@ void AsmPrinter::emitJumpTableSizesSection(const MachineJumpTableInfo *MJTI,
29913041

29923042
/// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the
29933043
/// current stream.
2994-
void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
3044+
void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo &MJTI,
29953045
const MachineBasicBlock *MBB,
29963046
unsigned UID) const {
29973047
assert(MBB && MBB->getNumber() >= 0 && "Invalid basic block");
29983048
const MCExpr *Value = nullptr;
2999-
switch (MJTI->getEntryKind()) {
3049+
switch (MJTI.getEntryKind()) {
30003050
case MachineJumpTableInfo::EK_Inline:
30013051
llvm_unreachable("Cannot emit EK_Inline jump table entry");
30023052
case MachineJumpTableInfo::EK_Custom32:
30033053
Value = MF->getSubtarget().getTargetLowering()->LowerCustomJumpTableEntry(
3004-
MJTI, MBB, UID, OutContext);
3054+
&MJTI, MBB, UID, OutContext);
30053055
break;
30063056
case MachineJumpTableInfo::EK_BlockAddress:
30073057
// EK_BlockAddress - Each entry is a plain address of block, e.g.:
@@ -3035,7 +3085,7 @@ void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
30353085
// If the .set directive avoids relocations, this is emitted as:
30363086
// .set L4_5_set_123, LBB123 - LJTI1_2
30373087
// .word L4_5_set_123
3038-
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
3088+
if (MJTI.getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
30393089
MAI->doesSetDirectiveSuppressReloc()) {
30403090
Value = MCSymbolRefExpr::create(GetJTSetSymbol(UID, MBB->getNumber()),
30413091
OutContext);
@@ -3051,7 +3101,7 @@ void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
30513101

30523102
assert(Value && "Unknown entry kind!");
30533103

3054-
unsigned EntrySize = MJTI->getEntrySize(getDataLayout());
3104+
unsigned EntrySize = MJTI.getEntrySize(getDataLayout());
30553105
OutStreamer->emitValue(Value, EntrySize);
30563106
}
30573107

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/CodeGen/BasicBlockSectionUtils.h"
2525
#include "llvm/CodeGen/MachineBasicBlock.h"
2626
#include "llvm/CodeGen/MachineFunction.h"
27+
#include "llvm/CodeGen/MachineJumpTableInfo.h"
2728
#include "llvm/CodeGen/MachineModuleInfo.h"
2829
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
2930
#include "llvm/IR/Comdat.h"
@@ -642,9 +643,11 @@ static StringRef getSectionPrefixForGlobal(SectionKind Kind, bool IsLarge) {
642643
static SmallString<128>
643644
getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
644645
Mangler &Mang, const TargetMachine &TM,
645-
unsigned EntrySize, bool UniqueSectionName) {
646+
unsigned EntrySize, bool UniqueSectionName,
647+
const MachineJumpTableEntry *JTE) {
646648
SmallString<128> Name =
647649
getSectionPrefixForGlobal(Kind, TM.isLargeGlobalValue(GO));
650+
648651
if (Kind.isMergeableCString()) {
649652
// We also need alignment here.
650653
// FIXME: this is getting the alignment of the character, not the
@@ -663,7 +666,11 @@ getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
663666

664667
bool HasPrefix = false;
665668
if (const auto *F = dyn_cast<Function>(GO)) {
666-
if (std::optional<StringRef> Prefix = F->getSectionPrefix()) {
669+
// Jump table hotness takes precedence over its enclosing function's hotness
670+
// if both are available.
671+
if (JTE && JTE->Hotness == DataHotness::Hot)
672+
raw_svector_ostream(Name) << ".hot";
673+
else if (std::optional<StringRef> Prefix = F->getSectionPrefix()) {
667674
raw_svector_ostream(Name) << '.' << *Prefix;
668675
HasPrefix = true;
669676
}
@@ -761,8 +768,8 @@ calcUniqueIDUpdateFlagsAndSize(const GlobalObject *GO, StringRef SectionName,
761768
// implicitly for this symbol e.g. .rodata.str1.1, then we don't need
762769
// to unique the section as the entry size for this symbol will be
763770
// compatible with implicitly created sections.
764-
SmallString<128> ImplicitSectionNameStem =
765-
getELFSectionNameForGlobal(GO, Kind, Mang, TM, EntrySize, false);
771+
SmallString<128> ImplicitSectionNameStem = getELFSectionNameForGlobal(
772+
GO, Kind, Mang, TM, EntrySize, false, /*MJTE=*/nullptr);
766773
if (SymbolMergeable &&
767774
Ctx.isELFImplicitMergeableSectionNamePrefix(SectionName) &&
768775
SectionName.starts_with(ImplicitSectionNameStem))
@@ -862,7 +869,8 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
862869
static MCSectionELF *selectELFSectionForGlobal(
863870
MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
864871
const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags,
865-
unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol) {
872+
unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol,
873+
const MachineJumpTableEntry *MJTE = nullptr) {
866874

867875
auto [Group, IsComdat, ExtraFlags] = getGlobalObjectInfo(GO, TM);
868876
Flags |= ExtraFlags;
@@ -881,7 +889,7 @@ static MCSectionELF *selectELFSectionForGlobal(
881889
}
882890
}
883891
SmallString<128> Name = getELFSectionNameForGlobal(
884-
GO, Kind, Mang, TM, EntrySize, UniqueSectionName);
892+
GO, Kind, Mang, TM, EntrySize, UniqueSectionName, MJTE);
885893

886894
// Use 0 as the unique ID for execute-only text.
887895
if (Kind.isExecuteOnly())
@@ -955,6 +963,12 @@ MCSection *TargetLoweringObjectFileELF::getUniqueSectionForFunction(
955963

956964
MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
957965
const Function &F, const TargetMachine &TM) const {
966+
return getSectionForJumpTable(F, TM, nullptr);
967+
}
968+
969+
MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
970+
const Function &F, const TargetMachine &TM,
971+
const MachineJumpTableEntry *JTE) const {
958972
// If the function can be removed, produce a unique section so that
959973
// the table doesn't prevent the removal.
960974
const Comdat *C = F.getComdat();
@@ -965,7 +979,7 @@ MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
965979
return selectELFSectionForGlobal(getContext(), &F, SectionKind::getReadOnly(),
966980
getMangler(), TM, EmitUniqueSection,
967981
ELF::SHF_ALLOC, &NextUniqueID,
968-
/* AssociatedSymbol */ nullptr);
982+
/* AssociatedSymbol */ nullptr, JTE);
969983
}
970984

971985
MCSection *TargetLoweringObjectFileELF::getSectionForLSDA(

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,11 @@ static cl::opt<bool>
263263
GCEmptyBlocks("gc-empty-basic-blocks", cl::init(false), cl::Hidden,
264264
cl::desc("Enable garbage-collecting empty basic blocks"));
265265

266+
/// Enable the static data splitter pass.
267+
static cl::opt<bool> SplitStaticData(
268+
"split-static-data", cl::Hidden, cl::init(false),
269+
cl::desc("Split static data sections using profile information"));
270+
266271
/// Allow standard passes to be disabled by command line options. This supports
267272
/// simple binary flags that either suppress the pass or do nothing.
268273
/// i.e. -disable-mypass=false has no effect.
@@ -1256,8 +1261,9 @@ void TargetPassConfig::addMachinePasses() {
12561261
"performance.\n";
12571262
}
12581263
}
1259-
addPass(createStaticDataSplitterPass());
12601264
addPass(createMachineFunctionSplitterPass());
1265+
if (SplitStaticData)
1266+
addPass(createStaticDataSplitterPass());
12611267
}
12621268
// We run the BasicBlockSections pass if either we need BB sections or BB
12631269
// address map (or both).

llvm/lib/Target/TargetLoweringObjectFile.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,12 @@ TargetLoweringObjectFile::SectionForGlobal(const GlobalObject *GO,
348348

349349
MCSection *TargetLoweringObjectFile::getSectionForJumpTable(
350350
const Function &F, const TargetMachine &TM) const {
351+
return getSectionForJumpTable(F, TM, nullptr);
352+
}
353+
354+
MCSection *TargetLoweringObjectFile::getSectionForJumpTable(
355+
const Function &F, const TargetMachine &TM,
356+
const MachineJumpTableEntry *JTE) const {
351357
Align Alignment(1);
352358
return getSectionForConstant(F.getDataLayout(),
353359
SectionKind::getReadOnly(), /*C=*/nullptr,

llvm/test/CodeGen/X86/jump-table-partition.ll

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,22 @@
22
; requires: asserts
33

44
; RUN: llc -stop-after=block-placement %s -o - | llc --run-pass=static-data-splitter -stats -x mir -o - 2>&1 | FileCheck %s --check-prefix=STAT
5+
; RUN: llc -enable-split-machine-functions -split-static-data --function-sections -data-sections %s -o - 2>&1 | FileCheck %s --check-prefix=SECTION
56

67
; `func_with_hot_jumptable` contains a hot jump table and `func_with_cold_jumptable` contains a cold one.
78
; `func_without_entry_count` simulates the functions without profile information (e.g., not instrumented or not profiled),
89
; it's jump table hotness is unknown and regarded as hot conservatively.
910
;
1011
; Tests stat messages are expected.
11-
; TODO: Update test to verify section suffixes when target-lowering and assembler changes are implemented.
12-
;
1312
; STAT-DAG: 1 static-data-splitter - Number of cold jump tables seen
1413
; STAT-DAG: 1 static-data-splitter - Number of hot jump tables seen
1514
; STAT-DAG: 1 static-data-splitter - Number of jump tables with unknown hotness
1615

16+
; TODO: Construct a test case where a hot function has a cold jump table.
17+
; SECTION: .section .rodata.hot.func_with_hot_jumptable
18+
; SECTION: .section .rodata.unlikely.func_with_cold_jumptable
19+
; SECTION: .section .rodata.hot.func_without_entry_count
20+
1721
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"
1822
target triple = "x86_64-unknown-linux-gnu"
1923

0 commit comments

Comments
 (0)