Skip to content

Commit

Permalink
Emit jump table with section suffix
Browse files Browse the repository at this point in the history
  • Loading branch information
mingmingl-llvm committed Jan 11, 2025
1 parent dd74827 commit 8d3a985
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 61 deletions.
8 changes: 6 additions & 2 deletions llvm/include/llvm/CodeGen/AsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,10 @@ class AsmPrinter : public MachineFunctionPass {
/// function to the current output stream.
virtual void emitJumpTableInfo();

virtual void emitJumpTables(ArrayRef<unsigned> JumpTableIndices,
MCSection *JumpTableSection, bool JTInDiffSection,
const MachineJumpTableInfo &MJTI);

/// Emit the specified global variable to the .s file.
virtual void emitGlobalVariable(const GlobalVariable *GV);

Expand Down Expand Up @@ -892,10 +896,10 @@ class AsmPrinter : public MachineFunctionPass {
// Internal Implementation Details
//===------------------------------------------------------------------===//

void emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
void emitJumpTableEntry(const MachineJumpTableInfo &MJTI,
const MachineBasicBlock *MBB, unsigned uid) const;

void emitJumpTableSizesSection(const MachineJumpTableInfo *MJTI,
void emitJumpTableSizesSection(const MachineJumpTableInfo &MJTI,
const Function &F) const;

void emitLLVMUsedList(const ConstantArray *InitList);
Expand Down
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ class TargetLoweringObjectFileELF : public TargetLoweringObjectFile {

MCSection *getSectionForJumpTable(const Function &F,
const TargetMachine &TM) const override;
MCSection *
getSectionForJumpTable(const Function &F, const TargetMachine &TM,
const MachineJumpTableEntry *JTE) const override;
MCSection *getSectionForLSDA(const Function &F, const MCSymbol &FnSym,
const TargetMachine &TM) const override;

Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/Target/TargetLoweringObjectFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Function;
class GlobalObject;
class GlobalValue;
class MachineBasicBlock;
class MachineJumpTableEntry;
class MachineModuleInfo;
class Mangler;
class MCContext;
Expand Down Expand Up @@ -132,6 +133,10 @@ class TargetLoweringObjectFile : public MCObjectFileInfo {

virtual MCSection *getSectionForJumpTable(const Function &F,
const TargetMachine &TM) const;
virtual MCSection *
getSectionForJumpTable(const Function &F, const TargetMachine &TM,
const MachineJumpTableEntry *JTE) const;

virtual MCSection *getSectionForLSDA(const Function &, const MCSymbol &,
const TargetMachine &) const {
return LSDASection;
Expand Down
108 changes: 82 additions & 26 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ static cl::opt<bool> BBAddrMapSkipEmitBBEntries(
"unnecessary for some PGOAnalysisMap features."),
cl::Hidden, cl::init(false));

static cl::opt<bool>
EmitStaticDataHotnessSuffix("emit-static-data-hotness-suffix", cl::Hidden,
cl::init(false), cl::ZeroOrMore,
cl::desc("Emit static data hotness suffix"));

static cl::opt<bool> EmitJumpTableSizesSection(
"emit-jump-table-sizes-section",
cl::desc("Emit a section containing jump table addresses and sizes"),
Expand Down Expand Up @@ -2861,7 +2866,6 @@ void AsmPrinter::emitConstantPool() {
// Print assembly representations of the jump tables used by the current
// function.
void AsmPrinter::emitJumpTableInfo() {
const DataLayout &DL = MF->getDataLayout();
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
if (!MJTI) return;
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return;
Expand All @@ -2876,42 +2880,94 @@ void AsmPrinter::emitJumpTableInfo() {
MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 ||
MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference64,
F);

std::vector<unsigned> JumpTableIndices;
if (!EmitStaticDataHotnessSuffix) {
for (unsigned JTI = 0, JTSize = JT.size(); JTI < JTSize; ++JTI)
JumpTableIndices.push_back(JTI);
emitJumpTables(JumpTableIndices, TLOF.getSectionForJumpTable(F, TM),
JTInDiffSection, *MJTI);
return;
}

// Iterate all jump tables, put hot jump table indices towards the beginning
// of the vector, and cold jump table indices towards the end.
int NextHotJumpTableIndex = 0, NextColdJumpTableIndex = JT.size() - 1;
JumpTableIndices.resize(JT.size());
for (unsigned JTI = 0, JTSize = JT.size(); JTI < JTSize; ++JTI) {
if (JT[JTI].Hotness == MachineFunctionDataHotness::Cold)
JumpTableIndices[NextColdJumpTableIndex--] = JTI;
else
JumpTableIndices[NextHotJumpTableIndex++] = JTI;
}

if (NextHotJumpTableIndex != 0) {
emitJumpTables(
ArrayRef<unsigned>(JumpTableIndices).take_front(NextHotJumpTableIndex),
TLOF.getSectionForJumpTable(F, TM, &JT[0]), JTInDiffSection, *MJTI);
}

if (NextHotJumpTableIndex != (int)JT.size()) {
// Retain the relative orders of original jump tables.
for (int L = NextHotJumpTableIndex, R = JT.size() - 1; L < R; ++L, --R)
std::swap(JumpTableIndices[L], JumpTableIndices[R]);

emitJumpTables(
ArrayRef<unsigned>(JumpTableIndices)
.take_back(JT.size() - NextHotJumpTableIndex),
TLOF.getSectionForJumpTable(F, TM, &JT[JumpTableIndices[NextHotJumpTableIndex]]),
JTInDiffSection, *MJTI);
}

return;
}

void AsmPrinter::emitJumpTables(ArrayRef<unsigned> JumpTableIndices,
MCSection *JumpTableSection,
bool JTInDiffSection,
const MachineJumpTableInfo &MJTI) {
if (JumpTableIndices.empty())
return;

const DataLayout &DL = MF->getDataLayout();
if (JTInDiffSection) {
// Drop it in the readonly section.
MCSection *ReadOnlySection = TLOF.getSectionForJumpTable(F, TM);
OutStreamer->switchSection(ReadOnlySection);
OutStreamer->switchSection(JumpTableSection);
}

emitAlignment(Align(MJTI->getEntryAlignment(DL)));
emitAlignment(Align(MJTI.getEntryAlignment(MF->getDataLayout())));

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

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

// If this jump table was deleted, ignore it.
if (JTBBs.empty()) continue;
if (JTBBs.empty())
continue;

// For the EK_LabelDifference32 entry, if using .set avoids a relocation,
/// emit a .set directive for each unique entry.
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
if (MJTI.getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
MAI->doesSetDirectiveSuppressReloc()) {
SmallPtrSet<const MachineBasicBlock*, 16> EmittedSets;
SmallPtrSet<const MachineBasicBlock *, 16> EmittedSets;
const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF,JTI,OutContext);
const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(
MF, JumpTableIndices[Index], OutContext);
for (const MachineBasicBlock *MBB : JTBBs) {
if (!EmittedSets.insert(MBB).second)
continue;

// .set LJTSet, LBB32-base
const MCExpr *LHS =
MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
OutStreamer->emitAssignment(GetJTSetSymbol(JTI, MBB->getNumber()),
MCBinaryExpr::createSub(LHS, Base,
OutContext));
MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
OutStreamer->emitAssignment(
GetJTSetSymbol(JumpTableIndices[Index], MBB->getNumber()),
MCBinaryExpr::createSub(LHS, Base, OutContext));
}
}

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

MCSymbol* JTISymbol = GetJTISymbol(JTI);
MCSymbol *JTISymbol = GetJTISymbol(JumpTableIndices[Index]);
OutStreamer->emitLabel(JTISymbol);

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

if (EmitJumpTableSizesSection)
emitJumpTableSizesSection(MJTI, F);
emitJumpTableSizesSection(MJTI, MF->getFunction());

if (!JTInDiffSection)
OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
}

void AsmPrinter::emitJumpTableSizesSection(const MachineJumpTableInfo *MJTI,
void AsmPrinter::emitJumpTableSizesSection(const MachineJumpTableInfo &MJTI,
const Function &F) const {
const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
const std::vector<MachineJumpTableEntry> &JT = MJTI.getJumpTables();

if (JT.empty())
return;
Expand Down Expand Up @@ -2991,17 +3047,17 @@ void AsmPrinter::emitJumpTableSizesSection(const MachineJumpTableInfo *MJTI,

/// EmitJumpTableEntry - Emit a jump table entry for the specified MBB to the
/// current stream.
void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo &MJTI,
const MachineBasicBlock *MBB,
unsigned UID) const {
assert(MBB && MBB->getNumber() >= 0 && "Invalid basic block");
const MCExpr *Value = nullptr;
switch (MJTI->getEntryKind()) {
switch (MJTI.getEntryKind()) {
case MachineJumpTableInfo::EK_Inline:
llvm_unreachable("Cannot emit EK_Inline jump table entry");
case MachineJumpTableInfo::EK_Custom32:
Value = MF->getSubtarget().getTargetLowering()->LowerCustomJumpTableEntry(
MJTI, MBB, UID, OutContext);
&MJTI, MBB, UID, OutContext);
break;
case MachineJumpTableInfo::EK_BlockAddress:
// EK_BlockAddress - Each entry is a plain address of block, e.g.:
Expand Down Expand Up @@ -3035,7 +3091,7 @@ void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI,
// If the .set directive avoids relocations, this is emitted as:
// .set L4_5_set_123, LBB123 - LJTI1_2
// .word L4_5_set_123
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
if (MJTI.getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 &&
MAI->doesSetDirectiveSuppressReloc()) {
Value = MCSymbolRefExpr::create(GetJTSetSymbol(UID, MBB->getNumber()),
OutContext);
Expand All @@ -3051,7 +3107,7 @@ void AsmPrinter::emitJumpTableEntry(const MachineJumpTableInfo *MJTI,

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

unsigned EntrySize = MJTI->getEntrySize(getDataLayout());
unsigned EntrySize = MJTI.getEntrySize(getDataLayout());
OutStreamer->emitValue(Value, EntrySize);
}

Expand Down
29 changes: 22 additions & 7 deletions llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "llvm/CodeGen/BasicBlockSectionUtils.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/IR/Comdat.h"
Expand Down Expand Up @@ -642,9 +643,11 @@ static StringRef getSectionPrefixForGlobal(SectionKind Kind, bool IsLarge) {
static SmallString<128>
getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,
Mangler &Mang, const TargetMachine &TM,
unsigned EntrySize, bool UniqueSectionName) {
unsigned EntrySize, bool UniqueSectionName,
const MachineJumpTableEntry *JTE) {
SmallString<128> Name =
getSectionPrefixForGlobal(Kind, TM.isLargeGlobalValue(GO));

if (Kind.isMergeableCString()) {
// We also need alignment here.
// FIXME: this is getting the alignment of the character, not the
Expand All @@ -663,7 +666,12 @@ getELFSectionNameForGlobal(const GlobalObject *GO, SectionKind Kind,

bool HasPrefix = false;
if (const auto *F = dyn_cast<Function>(GO)) {
if (std::optional<StringRef> Prefix = F->getSectionPrefix()) {
// Jump table hotness takes precedence over its enclosing function's hotness
// if both are available.
if (JTE) {
if (JTE->Hotness == MachineFunctionDataHotness::Hot)
raw_svector_ostream(Name) << ".hot";
} else if (std::optional<StringRef> Prefix = F->getSectionPrefix()) {
raw_svector_ostream(Name) << '.' << *Prefix;
HasPrefix = true;
}
Expand Down Expand Up @@ -761,8 +769,8 @@ calcUniqueIDUpdateFlagsAndSize(const GlobalObject *GO, StringRef SectionName,
// implicitly for this symbol e.g. .rodata.str1.1, then we don't need
// to unique the section as the entry size for this symbol will be
// compatible with implicitly created sections.
SmallString<128> ImplicitSectionNameStem =
getELFSectionNameForGlobal(GO, Kind, Mang, TM, EntrySize, false);
SmallString<128> ImplicitSectionNameStem = getELFSectionNameForGlobal(
GO, Kind, Mang, TM, EntrySize, false, /*MJTE=*/nullptr);
if (SymbolMergeable &&
Ctx.isELFImplicitMergeableSectionNamePrefix(SectionName) &&
SectionName.starts_with(ImplicitSectionNameStem))
Expand Down Expand Up @@ -862,7 +870,8 @@ MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
static MCSectionELF *selectELFSectionForGlobal(
MCContext &Ctx, const GlobalObject *GO, SectionKind Kind, Mangler &Mang,
const TargetMachine &TM, bool EmitUniqueSection, unsigned Flags,
unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol) {
unsigned *NextUniqueID, const MCSymbolELF *AssociatedSymbol,
const MachineJumpTableEntry *MJTE = nullptr) {

auto [Group, IsComdat, ExtraFlags] = getGlobalObjectInfo(GO, TM);
Flags |= ExtraFlags;
Expand All @@ -881,7 +890,7 @@ static MCSectionELF *selectELFSectionForGlobal(
}
}
SmallString<128> Name = getELFSectionNameForGlobal(
GO, Kind, Mang, TM, EntrySize, UniqueSectionName);
GO, Kind, Mang, TM, EntrySize, UniqueSectionName, MJTE);

// Use 0 as the unique ID for execute-only text.
if (Kind.isExecuteOnly())
Expand Down Expand Up @@ -955,6 +964,12 @@ MCSection *TargetLoweringObjectFileELF::getUniqueSectionForFunction(

MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
const Function &F, const TargetMachine &TM) const {
return getSectionForJumpTable(F, TM, nullptr);
}

MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
const Function &F, const TargetMachine &TM,
const MachineJumpTableEntry *JTE) const {
// If the function can be removed, produce a unique section so that
// the table doesn't prevent the removal.
const Comdat *C = F.getComdat();
Expand All @@ -965,7 +980,7 @@ MCSection *TargetLoweringObjectFileELF::getSectionForJumpTable(
return selectELFSectionForGlobal(getContext(), &F, SectionKind::getReadOnly(),
getMangler(), TM, EmitUniqueSection,
ELF::SHF_ALLOC, &NextUniqueID,
/* AssociatedSymbol */ nullptr);
/* AssociatedSymbol */ nullptr, JTE);
}

MCSection *TargetLoweringObjectFileELF::getSectionForLSDA(
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/CodeGen/TargetPassConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1261,9 +1261,9 @@ void TargetPassConfig::addMachinePasses() {
"performance.\n";
}
}
addPass(createMachineFunctionSplitterPass());
if (SplitStaticData)
addPass(createStaticDataSplitterPass());
addPass(createMachineFunctionSplitterPass());
}
// We run the BasicBlockSections pass if either we need BB sections or BB
// address map (or both).
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Target/TargetLoweringObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,12 @@ TargetLoweringObjectFile::SectionForGlobal(const GlobalObject *GO,

MCSection *TargetLoweringObjectFile::getSectionForJumpTable(
const Function &F, const TargetMachine &TM) const {
return getSectionForJumpTable(F, TM, nullptr);
}

MCSection *TargetLoweringObjectFile::getSectionForJumpTable(
const Function &F, const TargetMachine &TM,
const MachineJumpTableEntry *JTE) const {
Align Alignment(1);
return getSectionForConstant(F.getDataLayout(),
SectionKind::getReadOnly(), /*C=*/nullptr,
Expand Down
Loading

0 comments on commit 8d3a985

Please sign in to comment.