Skip to content

[BOLT][JT] Fix emitting jump table entry size #134050

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

yavtuk
Copy link
Contributor

@yavtuk yavtuk commented Apr 2, 2025

This patch adds getter & setter for jump table fields, also provide the fix for emit jump table functionality.
For x86_64 jump table footprint reduction pass can decrease the size of entries, for AArch64 the size can be increase for instrumentation or after reorder basic blocks passes. We should emit JT with output entry size

@llvmbot
Copy link
Member

llvmbot commented Apr 2, 2025

@llvm/pr-subscribers-bolt

Author: Alexey Moksyakov (yavtuk)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/134050.diff

9 Files Affected:

  • (modified) bolt/include/bolt/Core/JumpTable.h (+9-4)
  • (modified) bolt/lib/Core/BinaryContext.cpp (+2-2)
  • (modified) bolt/lib/Core/BinaryEmitter.cpp (+6-6)
  • (modified) bolt/lib/Core/BinaryFunction.cpp (+3-2)
  • (modified) bolt/lib/Core/BinaryFunctionProfile.cpp (+2-2)
  • (modified) bolt/lib/Passes/AsmDump.cpp (+1-1)
  • (modified) bolt/lib/Passes/IdenticalCodeFolding.cpp (+1-1)
  • (modified) bolt/lib/Passes/IndirectCallPromotion.cpp (+5-5)
  • (modified) bolt/lib/Passes/JTFootprintReduction.cpp (+3-3)
diff --git a/bolt/include/bolt/Core/JumpTable.h b/bolt/include/bolt/Core/JumpTable.h
index 52b9ccee1f7e1..e3e8851ec250f 100644
--- a/bolt/include/bolt/Core/JumpTable.h
+++ b/bolt/include/bolt/Core/JumpTable.h
@@ -45,6 +45,12 @@ class JumpTable : public BinaryData {
   JumpTable(const JumpTable &) = delete;
   JumpTable &operator=(const JumpTable &) = delete;
 
+  /// Size of the entry used for storage.
+  size_t EntrySize;
+
+  /// Size of the entry size we will write (we may use a more compact layout)
+  size_t OutputEntrySize;
+
 public:
   enum JumpTableType : char {
     JTT_NORMAL,
@@ -57,11 +63,10 @@ class JumpTable : public BinaryData {
     uint64_t Count{0};
   };
 
-  /// Size of the entry used for storage.
-  size_t EntrySize;
+  size_t getEntrySize() const { return EntrySize; }
 
-  /// Size of the entry size we will write (we may use a more compact layout)
-  size_t OutputEntrySize;
+  size_t getOutputEntrySize() const { return OutputEntrySize; }
+  void setOutputEntrySize(size_t val) { OutputEntrySize = val; }
 
   /// The type of this jump table.
   JumpTableType Type;
diff --git a/bolt/lib/Core/BinaryContext.cpp b/bolt/lib/Core/BinaryContext.cpp
index 80b15d7b79617..3c7ce6562aaae 100644
--- a/bolt/lib/Core/BinaryContext.cpp
+++ b/bolt/lib/Core/BinaryContext.cpp
@@ -747,7 +747,7 @@ void BinaryContext::populateJumpTables() {
     if (opts::StrictMode && JT->Type == JumpTable::JTT_PIC) {
       for (uint64_t Address = JT->getAddress();
            Address < JT->getAddress() + JT->getSize();
-           Address += JT->EntrySize) {
+           Address += JT->getEntrySize()) {
         DataPCRelocations.erase(DataPCRelocations.find(Address));
       }
     }
@@ -916,7 +916,7 @@ BinaryContext::duplicateJumpTable(BinaryFunction &Function, JumpTable *JT,
   (void)Found;
   MCSymbol *NewLabel = Ctx->createNamedTempSymbol("duplicatedJT");
   JumpTable *NewJT =
-      new JumpTable(*NewLabel, JT->getAddress(), JT->EntrySize, JT->Type,
+      new JumpTable(*NewLabel, JT->getAddress(), JT->getEntrySize(), JT->Type,
                     JumpTable::LabelMapType{{Offset, NewLabel}},
                     *getSectionForAddress(JT->getAddress()));
   NewJT->Parents = JT->Parents;
diff --git a/bolt/lib/Core/BinaryEmitter.cpp b/bolt/lib/Core/BinaryEmitter.cpp
index 1aad25242712f..c65f61ce65709 100644
--- a/bolt/lib/Core/BinaryEmitter.cpp
+++ b/bolt/lib/Core/BinaryEmitter.cpp
@@ -796,7 +796,7 @@ void BinaryEmitter::emitJumpTable(const JumpTable &JT, MCSection *HotSection,
     MCSymbol *CurrentLabel = It->second;
     uint64_t CurrentLabelCount = 0;
     for (unsigned Index = 0; Index < JT.Entries.size(); ++Index) {
-      auto LI = JT.Labels.find(Index * JT.EntrySize);
+      auto LI = JT.Labels.find(Index * JT.getEntrySize());
       if (LI != JT.Labels.end()) {
         LabelCounts[CurrentLabel] = CurrentLabelCount;
         CurrentLabel = LI->second;
@@ -807,7 +807,7 @@ void BinaryEmitter::emitJumpTable(const JumpTable &JT, MCSection *HotSection,
     LabelCounts[CurrentLabel] = CurrentLabelCount;
   } else {
     Streamer.switchSection(JT.Count > 0 ? HotSection : ColdSection);
-    Streamer.emitValueToAlignment(Align(JT.EntrySize));
+    Streamer.emitValueToAlignment(Align(JT.getEntrySize()));
   }
   MCSymbol *LastLabel = nullptr;
   uint64_t Offset = 0;
@@ -827,7 +827,7 @@ void BinaryEmitter::emitJumpTable(const JumpTable &JT, MCSection *HotSection,
           Streamer.switchSection(HotSection);
         else
           Streamer.switchSection(ColdSection);
-        Streamer.emitValueToAlignment(Align(JT.EntrySize));
+        Streamer.emitValueToAlignment(Align(JT.getEntrySize()));
       }
       // Emit all labels registered at the address of this jump table
       // to sync with our global symbol table.  We may have two labels
@@ -851,7 +851,7 @@ void BinaryEmitter::emitJumpTable(const JumpTable &JT, MCSection *HotSection,
       LastLabel = LI->second;
     }
     if (JT.Type == JumpTable::JTT_NORMAL) {
-      Streamer.emitSymbolValue(Entry, JT.OutputEntrySize);
+      Streamer.emitSymbolValue(Entry, JT.getOutputEntrySize());
     } else { // JTT_PIC
       const MCSymbolRefExpr *JTExpr =
           MCSymbolRefExpr::create(LastLabel, Streamer.getContext());
@@ -859,9 +859,9 @@ void BinaryEmitter::emitJumpTable(const JumpTable &JT, MCSection *HotSection,
           MCSymbolRefExpr::create(Entry, Streamer.getContext());
       const MCBinaryExpr *Value =
           MCBinaryExpr::createSub(E, JTExpr, Streamer.getContext());
-      Streamer.emitValue(Value, JT.EntrySize);
+      Streamer.emitValue(Value, JT.getEntrySize());
     }
-    Offset += JT.EntrySize;
+    Offset += JT.getEntrySize();
   }
 }
 
diff --git a/bolt/lib/Core/BinaryFunction.cpp b/bolt/lib/Core/BinaryFunction.cpp
index d1b293ada5fdc..5817760a09a5b 100644
--- a/bolt/lib/Core/BinaryFunction.cpp
+++ b/bolt/lib/Core/BinaryFunction.cpp
@@ -1967,7 +1967,8 @@ void BinaryFunction::postProcessJumpTables() {
 
     uint64_t EntryOffset = JTAddress - JT->getAddress();
     while (EntryOffset < JT->getSize()) {
-      uint64_t EntryAddress = JT->EntriesAsAddress[EntryOffset / JT->EntrySize];
+      uint64_t EntryAddress =
+          JT->EntriesAsAddress[EntryOffset / JT->getEntrySize()];
       uint64_t TargetOffset = EntryAddress - getAddress();
       if (TargetOffset < getSize()) {
         TakenBranches.emplace_back(JTSiteOffset, TargetOffset);
@@ -1976,7 +1977,7 @@ void BinaryFunction::postProcessJumpTables() {
           registerReferencedOffset(TargetOffset);
       }
 
-      EntryOffset += JT->EntrySize;
+      EntryOffset += JT->getEntrySize();
 
       // A label at the next entry means the end of this jump table.
       if (JT->Labels.count(EntryOffset))
diff --git a/bolt/lib/Core/BinaryFunctionProfile.cpp b/bolt/lib/Core/BinaryFunctionProfile.cpp
index 726da6a9d0829..db3feb17d3ea1 100644
--- a/bolt/lib/Core/BinaryFunctionProfile.cpp
+++ b/bolt/lib/Core/BinaryFunctionProfile.cpp
@@ -173,7 +173,7 @@ void BinaryFunction::postProcessProfile() {
     if (JT->Counts.empty())
       JT->Counts.resize(JT->Entries.size());
     auto EI = JT->Entries.begin();
-    uint64_t Delta = (JTAddress - JT->getAddress()) / JT->EntrySize;
+    uint64_t Delta = (JTAddress - JT->getAddress()) / JT->getEntrySize();
     EI += Delta;
     while (EI != JT->Entries.end()) {
       const BinaryBasicBlock *TargetBB = getBasicBlockForLabel(*EI);
@@ -187,7 +187,7 @@ void BinaryFunction::postProcessProfile() {
       ++Delta;
       ++EI;
       // A label marks the start of another jump table.
-      if (JT->Labels.count(Delta * JT->EntrySize))
+      if (JT->Labels.count(Delta * JT->getEntrySize()))
         break;
     }
   }
diff --git a/bolt/lib/Passes/AsmDump.cpp b/bolt/lib/Passes/AsmDump.cpp
index 08191669e72f3..5e51e7c485cc3 100644
--- a/bolt/lib/Passes/AsmDump.cpp
+++ b/bolt/lib/Passes/AsmDump.cpp
@@ -78,7 +78,7 @@ void dumpJumpTableSymbols(raw_ostream &OS, const JumpTable *JT, AsmPrinter &MAP,
   }
   OS << "\"" << JT->getName() << "\":\n";
   for (MCSymbol *JTEntry : JT->Entries)
-    MAP.OutStreamer->emitSymbolValue(JTEntry, JT->OutputEntrySize);
+    MAP.OutStreamer->emitSymbolValue(JTEntry, JT->getOutputEntrySize());
   OS << '\n';
 }
 
diff --git a/bolt/lib/Passes/IdenticalCodeFolding.cpp b/bolt/lib/Passes/IdenticalCodeFolding.cpp
index 8923562776cc4..bd64490ebf74e 100644
--- a/bolt/lib/Passes/IdenticalCodeFolding.cpp
+++ b/bolt/lib/Passes/IdenticalCodeFolding.cpp
@@ -84,7 +84,7 @@ static bool equalJumpTables(const JumpTable &JumpTableA,
                             const JumpTable &JumpTableB,
                             const BinaryFunction &FunctionA,
                             const BinaryFunction &FunctionB) {
-  if (JumpTableA.EntrySize != JumpTableB.EntrySize)
+  if (JumpTableA.getEntrySize() != JumpTableB.getEntrySize())
     return false;
 
   if (JumpTableA.Type != JumpTableB.Type)
diff --git a/bolt/lib/Passes/IndirectCallPromotion.cpp b/bolt/lib/Passes/IndirectCallPromotion.cpp
index 2b5a591f4c7a2..e5892e8819a3a 100644
--- a/bolt/lib/Passes/IndirectCallPromotion.cpp
+++ b/bolt/lib/Passes/IndirectCallPromotion.cpp
@@ -257,7 +257,7 @@ IndirectCallPromotion::getCallTargets(BinaryBasicBlock &BB,
         JT->Counts.empty() ? &DefaultJI : &JT->Counts[Range.first];
     const size_t JIAdj = JT->Counts.empty() ? 0 : 1;
     assert(JT->Type == JumpTable::JTT_PIC ||
-           JT->EntrySize == BC.AsmInfo->getCodePointerSize());
+           JT->getEntrySize() == BC.AsmInfo->getCodePointerSize());
     for (size_t I = Range.first; I < Range.second; ++I, JI += JIAdj) {
       MCSymbol *Entry = JT->Entries[I];
       const BinaryBasicBlock *ToBB = BF.getBasicBlockForLabel(Entry);
@@ -458,7 +458,7 @@ IndirectCallPromotion::maybeGetHotJumpTableTargets(BinaryBasicBlock &BB,
     if (!AccessInfo.MemoryObject && !AccessInfo.Offset)
       continue;
 
-    if (AccessInfo.Offset % JT->EntrySize != 0) // ignore bogus data
+    if (AccessInfo.Offset % JT->getEntrySize() != 0) // ignore bogus data
       return JumpTableInfoType();
 
     if (AccessInfo.MemoryObject) {
@@ -466,10 +466,10 @@ IndirectCallPromotion::maybeGetHotJumpTableTargets(BinaryBasicBlock &BB,
       if (!AccessInfo.MemoryObject->getName().starts_with(
               "JUMP_TABLE/" + Function.getOneName().str()))
         return JumpTableInfoType();
-      Index =
-          (AccessInfo.Offset - (ArrayStart - JT->getAddress())) / JT->EntrySize;
+      Index = (AccessInfo.Offset - (ArrayStart - JT->getAddress())) /
+              JT->getEntrySize();
     } else {
-      Index = (AccessInfo.Offset - ArrayStart) / JT->EntrySize;
+      Index = (AccessInfo.Offset - ArrayStart) / JT->getEntrySize();
     }
 
     // If Index is out of range it probably means the memory profiling data is
diff --git a/bolt/lib/Passes/JTFootprintReduction.cpp b/bolt/lib/Passes/JTFootprintReduction.cpp
index 71bdbba950df1..2fd7ab98d872b 100644
--- a/bolt/lib/Passes/JTFootprintReduction.cpp
+++ b/bolt/lib/Passes/JTFootprintReduction.cpp
@@ -119,7 +119,7 @@ void JTFootprintReduction::checkOpportunities(BinaryFunction &Function,
     TotalJTScore += CurScore;
     if (!BlacklistedJTs.count(JT)) {
       OptimizedScore += CurScore;
-      if (JT->EntrySize == 8)
+      if (JT->getEntrySize() == 8)
         BytesSaved += JT->getSize() >> 1;
     }
   }
@@ -161,7 +161,7 @@ bool JTFootprintReduction::tryOptimizeNonPIC(
                            MCOperand::createReg(Index), Offset, RegOp);
   BC.MIB->setJumpTable(NewFrag.back(), JTAddr, Index);
 
-  JumpTable->OutputEntrySize = 4;
+  JumpTable->setOutputEntrySize(4);
 
   BB.replaceInstruction(Inst, NewFrag.begin(), NewFrag.end());
   return true;
@@ -200,7 +200,7 @@ bool JTFootprintReduction::tryOptimizePIC(BinaryContext &BC,
                            MCOperand::createReg(Index), JumpTableRef, RegOp);
   BC.MIB->setJumpTable(NewFrag.back(), JTAddr, Index);
 
-  JumpTable->OutputEntrySize = 4;
+  JumpTable->setOutputEntrySize(4);
   // DePICify
   JumpTable->Type = JumpTable::JTT_NORMAL;
 

yavtuk added 2 commits April 14, 2025 12:01
JTFootprintReduction pass can change the output entry size for JT.
For instrumentation a JT entry size can be increased.
@yavtuk yavtuk force-pushed the bolt-jt-getter-setter branch from ee3f0f1 to 5935478 Compare April 14, 2025 09:08
@yavtuk yavtuk changed the title Add getter/setter for jump table entry size fields [BOLT][JT] Fix emitting jump table entry size Apr 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants