[llvm] [GlobalISel][IRTranslator] Add tiny hot caches for Value->VReg/Type and Alloca->FI (NFCI) (PR #158092)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 11 07:58:31 PDT 2025
https://github.com/steven-studio created https://github.com/llvm/llvm-project/pull/158092
What:
Introduces two small ring-buffer hot caches in IRTranslator:
• A hot-path cache for Value* -> VRegListT* and Type* -> OffsetListT* lookups.
• A hot-path cache for AllocaInst* -> FrameIndex lookups.
Why:
Reduces frequent DenseMap probes on hot paths without changing semantics.
Scope/Risk:
NFCI (No Functional Change Intended). Only affects lookup fast paths; expected to have zero behavioral impact.
Testing:
Passed local check-llvm runs; CI regressions are not expected.
Style:
Formatted using git clang-format.
>From 9d54c61a1604a50b4c3f6d75fe3efe1ac948201d Mon Sep 17 00:00:00 2001
From: steven-studio <stevenyu.supreme at gmail.com>
Date: Thu, 11 Sep 2025 22:27:16 +0800
Subject: [PATCH] [GlobalISel][IRTranslator] Add tiny hot caches for
Value->VReg/Type and Alloca->FI (NFCI)
---
.../llvm/CodeGen/GlobalISel/IRTranslator.h | 74 +++++++++++++++++--
1 file changed, 68 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
index 3d7ccd55ee042..72cb92b3d70be 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
@@ -27,6 +27,7 @@
#include "llvm/CodeGen/SwiftErrorValueTracking.h"
#include "llvm/CodeGen/SwitchLoweringUtils.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/CodeGen.h"
#include <memory>
#include <utility>
@@ -87,19 +88,27 @@ class IRTranslator : public MachineFunctionPass {
inline const_vreg_iterator vregs_end() const { return ValToVRegs.end(); }
VRegListT *getVRegs(const Value &V) {
+ if (auto *H = probeHotV(V)) return H;
auto It = ValToVRegs.find(&V);
- if (It != ValToVRegs.end())
+ if (It != ValToVRegs.end()) {
+ pushHotV(V, It->second);
return It->second;
-
- return insertVRegs(V);
+ }
+ auto *P = insertVRegs(V);
+ pushHotV(V, P);
+ return P;
}
OffsetListT *getOffsets(const Value &V) {
+ if (auto *H = probeHotT(V)) return H;
auto It = TypeToOffsets.find(V.getType());
- if (It != TypeToOffsets.end())
+ if (It != TypeToOffsets.end()) {
+ pushHotT(V, It->second);
return It->second;
-
- return insertOffsets(V);
+ }
+ auto *P = insertOffsets(V);
+ pushHotT(V, P);
+ return P;
}
const_vreg_iterator findVRegs(const Value &V) const {
@@ -113,9 +122,52 @@ class IRTranslator : public MachineFunctionPass {
TypeToOffsets.clear();
VRegAlloc.DestroyAll();
OffsetAlloc.DestroyAll();
+ // Clear the small hot caches.
+ for (unsigned i=0;i<HotN;++i){ HotVRegs[i]={}; HotOffsets[i]={}; }
+ HotVHead = HotTHead = 0;
}
private:
+ // --- Tiny ring-buffer hot cache (reduces DenseMap probes on hot paths). ---
+ static constexpr unsigned HotN = 8;
+ struct HotEntryV {
+ const Value *Key = nullptr;
+ VRegListT *Val = nullptr;
+ };
+ struct HotEntryT {
+ const Type *Key = nullptr;
+ OffsetListT *Val = nullptr;
+ };
+ HotEntryV HotVRegs[HotN];
+ HotEntryT HotOffsets[HotN];
+ unsigned HotVHead = 0, HotTHead = 0;
+
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ VRegListT *probeHotV(const Value &V) const {
+ // A small linear scan is fine (HotN is tiny).
+ for (unsigned i = 0; i < HotN; ++i)
+ if (HotVRegs[i].Key == &V) return HotVRegs[i].Val;
+ return nullptr;
+ }
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ void pushHotV(const Value &V, VRegListT *Ptr) {
+ HotVRegs[HotVHead] = {&V, Ptr};
+ HotVHead = (HotVHead + 1) % HotN;
+ }
+
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ OffsetListT *probeHotT(const Value &V) const {
+ const Type *Ty = V.getType();
+ for (unsigned i = 0; i < HotN; ++i)
+ if (HotOffsets[i].Key == Ty) return HotOffsets[i].Val;
+ return nullptr;
+ }
+ LLVM_ATTRIBUTE_ALWAYS_INLINE
+ void pushHotT(const Value &V, OffsetListT *Ptr) {
+ HotOffsets[HotTHead] = {V.getType(), Ptr};
+ HotTHead = (HotTHead + 1) % HotN;
+ }
+
VRegListT *insertVRegs(const Value &V) {
assert(!ValToVRegs.contains(&V) && "Value already exists");
@@ -163,6 +215,16 @@ class IRTranslator : public MachineFunctionPass {
/// this function.
DenseMap<const AllocaInst *, int> FrameIndices;
+ /// Tiny ring buffer cache for frequently accessed FrameIndices.
+ /// Avoids DenseMap lookup when there are repeated queries for the same allocas.
+ static constexpr unsigned FIHotN = 8;
+ struct FIHot {
+ const AllocaInst *AI = nullptr;
+ int FI = 0;
+ };
+ FIHot FIHotCache[FIHotN];
+ unsigned FIHotHead = 0;
+
SwiftErrorValueTracking SwiftError;
/// \name Methods for translating form LLVM IR to MachineInstr.
More information about the llvm-commits
mailing list