Skip to content

Commit 9747bb1

Browse files
[CodeGen][StaticDataSplitter]Support constant pool partitioning (#129781)
This is a follow-up patch of #125756 In this PR, static-data-splitter pass produces the aggregated profile counts of constants for constant pools in a global state (`StateDataProfileInfo`), and asm printer consumes the profile counts to produce `.hot` or `.unlikely` prefixes. This implementation covers both x86 and aarch64 asm printer.
1 parent 976a384 commit 9747bb1

File tree

11 files changed

+460
-28
lines changed

11 files changed

+460
-28
lines changed

llvm/include/llvm/CodeGen/AsmPrinter.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "llvm/ADT/DenseMap.h"
1919
#include "llvm/ADT/MapVector.h"
2020
#include "llvm/ADT/SmallVector.h"
21+
#include "llvm/Analysis/ProfileSummaryInfo.h"
22+
#include "llvm/Analysis/StaticDataProfileInfo.h"
2123
#include "llvm/BinaryFormat/Dwarf.h"
2224
#include "llvm/CodeGen/DwarfStringPoolEntry.h"
2325
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -132,6 +134,12 @@ class AsmPrinter : public MachineFunctionPass {
132134
/// default, this is equal to CurrentFnSym.
133135
MCSymbol *CurrentFnSymForSize = nullptr;
134136

137+
/// Provides the profile information for constants.
138+
const StaticDataProfileInfo *SDPI = nullptr;
139+
140+
/// The profile summary information.
141+
const ProfileSummaryInfo *PSI = nullptr;
142+
135143
/// Map a basic block section ID to the begin and end symbols of that section
136144
/// which determine the section's range.
137145
struct MBBSectionRange {
@@ -330,6 +338,10 @@ class AsmPrinter : public MachineFunctionPass {
330338
DwarfUsesRelocationsAcrossSections = Enable;
331339
}
332340

341+
/// Returns a section suffix (hot or unlikely) for the constant if profiles
342+
/// are available. Returns empty string otherwise.
343+
StringRef getConstantSectionSuffix(const Constant *C) const;
344+
333345
//===------------------------------------------------------------------===//
334346
// XRay instrumentation implementation.
335347
//===------------------------------------------------------------------===//

llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {
6666
const Constant *C,
6767
Align &Alignment) const override;
6868

69+
/// Similar to the function above, but append \p SectionSuffix to the section
70+
/// name.
71+
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
72+
const Constant *C, Align &Alignment,
73+
StringRef SectionSuffix) const override;
74+
6975
MCSection *getExplicitSectionGlobal(const GlobalObject *GO, SectionKind Kind,
7076
const TargetMachine &TM) const override;
7177

llvm/include/llvm/Target/TargetLoweringObjectFile.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,13 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {
104104
SectionKind Kind, const Constant *C,
105105
Align &Alignment) const;
106106

107+
/// Similar to the function above, but append \p SectionSuffix to the section
108+
/// name.
109+
virtual MCSection *getSectionForConstant(const DataLayout &DL,
110+
SectionKind Kind, const Constant *C,
111+
Align &Alignment,
112+
StringRef SectionSuffix) const;
113+
107114
virtual MCSection *
108115
getSectionForMachineBasicBlock(const Function &F,
109116
const MachineBasicBlock &MBB,

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2769,6 +2769,13 @@ namespace {
27692769

27702770
} // end anonymous namespace
27712771

2772+
StringRef AsmPrinter::getConstantSectionSuffix(const Constant *C) const {
2773+
if (TM.Options.EnableStaticDataPartitioning && C && SDPI && PSI)
2774+
return SDPI->getConstantSectionPrefix(C, PSI);
2775+
2776+
return "";
2777+
}
2778+
27722779
/// EmitConstantPool - Print to the current output stream assembly
27732780
/// representations of the constants in the constant pool MCP. This is
27742781
/// used to print out constants which have been "spilled to memory" by
@@ -2792,7 +2799,7 @@ void AsmPrinter::emitConstantPool() {
27922799
C = CPE.Val.ConstVal;
27932800

27942801
MCSection *S = getObjFileLowering().getSectionForConstant(
2795-
getDataLayout(), Kind, C, Alignment);
2802+
getDataLayout(), Kind, C, Alignment, getConstantSectionSuffix(C));
27962803

27972804
// The number of sections are small, just do a linear search from the
27982805
// last section to the first.

llvm/lib/CodeGen/StaticDataSplitter.cpp

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// for the following types of static data:
1111
// - Jump tables
1212
// - Module-internal global variables
13-
// - Constant pools (TODO)
13+
// - Constant pools
1414
//
1515
// For the original RFC of this pass please see
1616
// https://discourse.llvm.org/t/rfc-profile-guided-static-data-partitioning/83744
@@ -60,8 +60,8 @@ class StaticDataSplitter : public MachineFunctionPass {
6060

6161
// Returns the constant if the operand refers to a global variable or constant
6262
// that gets lowered to static data sections. Otherwise, return nullptr.
63-
const Constant *getConstant(const MachineOperand &Op,
64-
const TargetMachine &TM);
63+
const Constant *getConstant(const MachineOperand &Op, const TargetMachine &TM,
64+
const MachineConstantPool *MCP);
6565

6666
// Use profiles to partition static data.
6767
bool partitionStaticDataWithProfiles(MachineFunction &MF);
@@ -89,8 +89,11 @@ class StaticDataSplitter : public MachineFunctionPass {
8989
AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
9090
AU.addRequired<ProfileSummaryInfoWrapperPass>();
9191
AU.addRequired<StaticDataProfileInfoWrapperPass>();
92-
// This pass does not modify the CFG.
93-
AU.setPreservesCFG();
92+
// This pass does not modify any required analysis results except
93+
// StaticDataProfileInfoWrapperPass, but StaticDataProfileInfoWrapperPass
94+
// is made an immutable pass that it won't be re-scheduled by pass manager
95+
// anyway. So mark setPreservesAll() here for faster compile time.
96+
AU.setPreservesAll();
9497
}
9598

9699
bool runOnMachineFunction(MachineFunction &MF) override;
@@ -119,40 +122,63 @@ bool StaticDataSplitter::runOnMachineFunction(MachineFunction &MF) {
119122
return Changed;
120123
}
121124

122-
const Constant *StaticDataSplitter::getConstant(const MachineOperand &Op,
123-
const TargetMachine &TM) {
124-
if (!Op.isGlobal())
125+
const Constant *
126+
StaticDataSplitter::getConstant(const MachineOperand &Op,
127+
const TargetMachine &TM,
128+
const MachineConstantPool *MCP) {
129+
if (!Op.isGlobal() && !Op.isCPI())
125130
return nullptr;
126131

127-
// Find global variables with local linkage.
128-
const GlobalVariable *GV = getLocalLinkageGlobalVariable(Op.getGlobal());
129-
// Skip 'llvm.'-prefixed global variables conservatively because they are
130-
// often handled specially, and skip those not in static data sections.
131-
if (!GV || GV->getName().starts_with("llvm.") ||
132-
!inStaticDataSection(*GV, TM))
132+
if (Op.isGlobal()) {
133+
// Find global variables with local linkage.
134+
const GlobalVariable *GV = getLocalLinkageGlobalVariable(Op.getGlobal());
135+
// Skip 'llvm.'-prefixed global variables conservatively because they are
136+
// often handled specially, and skip those not in static data
137+
// sections.
138+
if (!GV || GV->getName().starts_with("llvm.") ||
139+
!inStaticDataSection(*GV, TM))
140+
return nullptr;
141+
return GV;
142+
}
143+
assert(Op.isCPI() && "Op must be constant pool index in this branch");
144+
int CPI = Op.getIndex();
145+
if (CPI == -1)
146+
return nullptr;
147+
148+
assert(MCP != nullptr && "Constant pool info is not available.");
149+
const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
150+
151+
if (CPE.isMachineConstantPoolEntry())
133152
return nullptr;
134-
return GV;
153+
154+
return CPE.Val.ConstVal;
135155
}
136156

137157
bool StaticDataSplitter::partitionStaticDataWithProfiles(MachineFunction &MF) {
138-
int NumChangedJumpTables = 0;
158+
// If any of the static data (jump tables, global variables, constant pools)
159+
// are captured by the analysis, set `Changed` to true. Note this pass won't
160+
// invalidate any analysis pass (see `getAnalysisUsage` above), so the main
161+
// purpose of tracking and conveying the change (to pass manager) is
162+
// informative as opposed to invalidating any analysis results. As an example
163+
// of where this information is useful, `PMDataManager::dumpPassInfo` will
164+
// only dump pass info if a local change happens, otherwise a pass appears as
165+
// "skipped".
166+
bool Changed = false;
139167

140-
const TargetMachine &TM = MF.getTarget();
141168
MachineJumpTableInfo *MJTI = MF.getJumpTableInfo();
142169

143170
// Jump table could be used by either terminating instructions or
144171
// non-terminating ones, so we walk all instructions and use
145172
// `MachineOperand::isJTI()` to identify jump table operands.
146-
// Similarly, `MachineOperand::isCPI()` can identify constant pool usages
147-
// in the same loop.
173+
// Similarly, `MachineOperand::isCPI()` is used to identify constant pool
174+
// usages in the same loop.
148175
for (const auto &MBB : MF) {
176+
std::optional<uint64_t> Count = MBFI->getBlockProfileCount(&MBB);
149177
for (const MachineInstr &I : MBB) {
150178
for (const MachineOperand &Op : I.operands()) {
151-
if (!Op.isJTI() && !Op.isGlobal())
179+
if (!Op.isJTI() && !Op.isGlobal() && !Op.isCPI())
152180
continue;
153181

154-
std::optional<uint64_t> Count = MBFI->getBlockProfileCount(&MBB);
155-
156182
if (Op.isJTI()) {
157183
assert(MJTI != nullptr && "Jump table info is not available.");
158184
const int JTI = Op.getIndex();
@@ -168,15 +194,16 @@ bool StaticDataSplitter::partitionStaticDataWithProfiles(MachineFunction &MF) {
168194
if (Count && PSI->isColdCount(*Count))
169195
Hotness = MachineFunctionDataHotness::Cold;
170196

171-
if (MJTI->updateJumpTableEntryHotness(JTI, Hotness))
172-
++NumChangedJumpTables;
173-
} else if (const Constant *C = getConstant(Op, TM)) {
197+
Changed |= MJTI->updateJumpTableEntryHotness(JTI, Hotness);
198+
} else if (const Constant *C =
199+
getConstant(Op, MF.getTarget(), MF.getConstantPool())) {
174200
SDPI->addConstantProfileCount(C, Count);
201+
Changed = true;
175202
}
176203
}
177204
}
178205
}
179-
return NumChangedJumpTables > 0;
206+
return Changed;
180207
}
181208

182209
const GlobalVariable *
@@ -218,7 +245,8 @@ void StaticDataSplitter::annotateStaticDataWithoutProfiles(
218245
for (const auto &MBB : MF)
219246
for (const MachineInstr &I : MBB)
220247
for (const MachineOperand &Op : I.operands())
221-
if (const Constant *C = getConstant(Op, MF.getTarget()))
248+
if (const Constant *C =
249+
getConstant(Op, MF.getTarget(), MF.getConstantPool()))
222250
SDPI->addConstantProfileCount(C, std::nullopt);
223251
}
224252

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,41 @@ MCSection *TargetLoweringObjectFileELF::getSectionForConstant(
10681068
return DataRelROSection;
10691069
}
10701070

1071+
MCSection *TargetLoweringObjectFileELF::getSectionForConstant(
1072+
const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,
1073+
StringRef SectionSuffix) const {
1074+
// TODO: Share code between this function and
1075+
// MCObjectInfo::initELFMCObjectFileInfo.
1076+
if (SectionSuffix.empty())
1077+
return getSectionForConstant(DL, Kind, C, Alignment);
1078+
1079+
auto &Context = getContext();
1080+
if (Kind.isMergeableConst4() && MergeableConst4Section)
1081+
return Context.getELFSection(".rodata.cst4." + SectionSuffix,
1082+
ELF::SHT_PROGBITS,
1083+
ELF::SHF_ALLOC | ELF::SHF_MERGE, 4);
1084+
if (Kind.isMergeableConst8() && MergeableConst8Section)
1085+
return Context.getELFSection(".rodata.cst8." + SectionSuffix,
1086+
ELF::SHT_PROGBITS,
1087+
ELF::SHF_ALLOC | ELF::SHF_MERGE, 8);
1088+
if (Kind.isMergeableConst16() && MergeableConst16Section)
1089+
return Context.getELFSection(".rodata.cst16." + SectionSuffix,
1090+
ELF::SHT_PROGBITS,
1091+
ELF::SHF_ALLOC | ELF::SHF_MERGE, 16);
1092+
if (Kind.isMergeableConst32() && MergeableConst32Section)
1093+
return Context.getELFSection(".rodata.cst32." + SectionSuffix,
1094+
ELF::SHT_PROGBITS,
1095+
ELF::SHF_ALLOC | ELF::SHF_MERGE, 32);
1096+
if (Kind.isReadOnly())
1097+
return Context.getELFSection(".rodata." + SectionSuffix, ELF::SHT_PROGBITS,
1098+
ELF::SHF_ALLOC);
1099+
1100+
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
1101+
return Context.getELFSection(".data.rel.ro." + SectionSuffix,
1102+
ELF::SHT_PROGBITS,
1103+
ELF::SHF_ALLOC | ELF::SHF_WRITE);
1104+
}
1105+
10711106
/// Returns a unique section for the given machine basic block.
10721107
MCSection *TargetLoweringObjectFileELF::getSectionForMachineBasicBlock(
10731108
const Function &F, const MachineBasicBlock &MBB,

llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,12 @@ class AArch64AsmPrinter : public AsmPrinter {
226226
}
227227

228228
bool runOnMachineFunction(MachineFunction &MF) override {
229+
if (auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
230+
PSI = &PSIW->getPSI();
231+
if (auto *SDPIW =
232+
getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
233+
SDPI = &SDPIW->getStaticDataProfileInfo();
234+
229235
AArch64FI = MF.getInfo<AArch64FunctionInfo>();
230236
STI = &MF.getSubtarget<AArch64Subtarget>();
231237

llvm/lib/Target/TargetLoweringObjectFile.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,18 @@ MCSection *TargetLoweringObjectFile::getSectionForConstant(
385385
return DataSection;
386386
}
387387

388+
MCSection *TargetLoweringObjectFile::getSectionForConstant(
389+
const DataLayout &DL, SectionKind Kind, const Constant *C, Align &Alignment,
390+
StringRef SectionPrefix) const {
391+
// Fallback to `getSectionForConstant` without `SectionPrefix` parameter if it
392+
// is empty.
393+
if (SectionPrefix.empty())
394+
return getSectionForConstant(DL, Kind, C, Alignment);
395+
report_fatal_error(
396+
"TargetLoweringObjectFile::getSectionForConstant that "
397+
"accepts SectionPrefix is not implemented for the object file format");
398+
}
399+
388400
MCSection *TargetLoweringObjectFile::getSectionForMachineBasicBlock(
389401
const Function &F, const MachineBasicBlock &MBB,
390402
const TargetMachine &TM) const {

llvm/lib/Target/X86/X86AsmPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "X86InstrInfo.h"
2121
#include "X86MachineFunctionInfo.h"
2222
#include "X86Subtarget.h"
23+
#include "llvm/Analysis/StaticDataProfileInfo.h"
2324
#include "llvm/BinaryFormat/COFF.h"
2425
#include "llvm/BinaryFormat/ELF.h"
2526
#include "llvm/CodeGen/MachineConstantPool.h"
@@ -61,6 +62,11 @@ X86AsmPrinter::X86AsmPrinter(TargetMachine &TM,
6162
/// runOnMachineFunction - Emit the function body.
6263
///
6364
bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
65+
if (auto *PSIW = getAnalysisIfAvailable<ProfileSummaryInfoWrapperPass>())
66+
PSI = &PSIW->getPSI();
67+
if (auto *SDPIW = getAnalysisIfAvailable<StaticDataProfileInfoWrapperPass>())
68+
SDPI = &SDPIW->getStaticDataProfileInfo();
69+
6470
Subtarget = &MF.getSubtarget<X86Subtarget>();
6571

6672
SMShadowTracker.startFunction(MF);

0 commit comments

Comments
 (0)