Skip to content

Conversation

@Ralender
Copy link
Collaborator

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Oct 28, 2025

@llvm/pr-subscribers-backend-amdgpu

Author: None (Ralender)

Changes

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

4 Files Affected:

  • (modified) llvm/include/llvm/CodeGen/LiveStacks.h (+19-25)
  • (modified) llvm/lib/CodeGen/LiveStacks.cpp (+22-19)
  • (modified) llvm/lib/CodeGen/StackSlotColoring.cpp (+5-15)
  • (modified) llvm/lib/Target/AMDGPU/AMDGPUMarkLastScratchLoad.cpp (+3-3)
diff --git a/llvm/include/llvm/CodeGen/LiveStacks.h b/llvm/include/llvm/CodeGen/LiveStacks.h
index 02c640bfc4a93..3b4550901dc7e 100644
--- a/llvm/include/llvm/CodeGen/LiveStacks.h
+++ b/llvm/include/llvm/CodeGen/LiveStacks.h
@@ -40,49 +40,43 @@ class LiveStacks {
   ///
   VNInfo::Allocator VNInfoAllocator;
 
-  /// S2IMap - Stack slot indices to live interval mapping.
-  using SS2IntervalMap = std::unordered_map<int, LiveInterval>;
-  SS2IntervalMap S2IMap;
-
-  /// S2RCMap - Stack slot indices to register class mapping.
-  std::map<int, const TargetRegisterClass *> S2RCMap;
+  int StartIdx = -1;
+  SmallVector<LiveInterval *> S2LI;
+  SmallVector<const TargetRegisterClass *> S2RC;
 
 public:
-  using iterator = SS2IntervalMap::iterator;
-  using const_iterator = SS2IntervalMap::const_iterator;
+  using iterator = SmallVector<LiveInterval *>::iterator;
+  using const_iterator = SmallVector<LiveInterval *>::const_iterator;
 
-  const_iterator begin() const { return S2IMap.begin(); }
-  const_iterator end() const { return S2IMap.end(); }
-  iterator begin() { return S2IMap.begin(); }
-  iterator end() { return S2IMap.end(); }
+  const_iterator begin() const { return S2LI.begin(); }
+  const_iterator end() const { return S2LI.end(); }
+  iterator begin() { return S2LI.begin(); }
+  iterator end() { return S2LI.end(); }
 
-  unsigned getNumIntervals() const { return (unsigned)S2IMap.size(); }
+  unsigned getStartIdx() const { return StartIdx; }
+  unsigned getNumIntervals() const { return (unsigned)S2LI.size(); }
 
   LiveInterval &getOrCreateInterval(int Slot, const TargetRegisterClass *RC);
 
   LiveInterval &getInterval(int Slot) {
     assert(Slot >= 0 && "Spill slot indice must be >= 0");
-    SS2IntervalMap::iterator I = S2IMap.find(Slot);
-    assert(I != S2IMap.end() && "Interval does not exist for stack slot");
-    return I->second;
+    return *S2LI[Slot - StartIdx];
   }
 
   const LiveInterval &getInterval(int Slot) const {
     assert(Slot >= 0 && "Spill slot indice must be >= 0");
-    SS2IntervalMap::const_iterator I = S2IMap.find(Slot);
-    assert(I != S2IMap.end() && "Interval does not exist for stack slot");
-    return I->second;
+    return *S2LI[Slot - StartIdx];
   }
 
-  bool hasInterval(int Slot) const { return S2IMap.count(Slot); }
+  bool hasInterval(int Slot) const {
+    if (Slot < StartIdx || StartIdx == -1)
+      return false;
+    return !getInterval(Slot).empty();
+  }
 
   const TargetRegisterClass *getIntervalRegClass(int Slot) const {
     assert(Slot >= 0 && "Spill slot indice must be >= 0");
-    std::map<int, const TargetRegisterClass *>::const_iterator I =
-        S2RCMap.find(Slot);
-    assert(I != S2RCMap.end() &&
-           "Register class info does not exist for stack slot");
-    return I->second;
+    return S2RC[Slot - StartIdx];
   }
 
   VNInfo::Allocator &getVNInfoAllocator() { return VNInfoAllocator; }
diff --git a/llvm/lib/CodeGen/LiveStacks.cpp b/llvm/lib/CodeGen/LiveStacks.cpp
index c07d985a09d1f..ea158b2d96a4e 100644
--- a/llvm/lib/CodeGen/LiveStacks.cpp
+++ b/llvm/lib/CodeGen/LiveStacks.cpp
@@ -37,10 +37,12 @@ void LiveStacksWrapperLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
 }
 
 void LiveStacks::releaseMemory() {
+  for (int Idx = 0; Idx < (int)S2LI.size(); ++Idx)
+    S2LI[Idx]->~LiveInterval();
   // Release VNInfo memory regions, VNInfo objects don't need to be dtor'd.
   VNInfoAllocator.Reset();
-  S2IMap.clear();
-  S2RCMap.clear();
+  S2LI.clear();
+  S2RC.clear();
 }
 
 void LiveStacks::init(MachineFunction &MF) {
@@ -52,20 +54,22 @@ void LiveStacks::init(MachineFunction &MF) {
 LiveInterval &
 LiveStacks::getOrCreateInterval(int Slot, const TargetRegisterClass *RC) {
   assert(Slot >= 0 && "Spill slot indice must be >= 0");
-  SS2IntervalMap::iterator I = S2IMap.find(Slot);
-  if (I == S2IMap.end()) {
-    I = S2IMap
-            .emplace(
-                std::piecewise_construct, std::forward_as_tuple(Slot),
-                std::forward_as_tuple(Register::index2StackSlot(Slot), 0.0F))
-            .first;
-    S2RCMap.insert(std::make_pair(Slot, RC));
+  if (StartIdx == -1)
+    StartIdx = Slot;
+
+  int Idx = Slot - StartIdx;
+  assert(Idx >= 0 && "Slot not in order ?");
+  if (Idx < (int)S2LI.size()) {
+    S2RC[Idx] = TRI->getCommonSubClass(S2RC[Idx], RC);
   } else {
-    // Use the largest common subclass register class.
-    const TargetRegisterClass *&OldRC = S2RCMap[Slot];
-    OldRC = TRI->getCommonSubClass(OldRC, RC);
+    S2RC.resize(Idx + 1);
+    S2LI.resize(Idx + 1);
+    S2LI[Idx] = this->VNInfoAllocator.Allocate<LiveInterval>();
+    new (S2LI[Idx]) LiveInterval(Register::index2StackSlot(Slot), 0.0F);
+    S2RC[Idx] = RC;
   }
-  return I->second;
+  assert(S2RC.size() == S2LI.size());
+  return *S2LI[Idx];
 }
 
 AnalysisKey LiveStacksAnalysis::Key;
@@ -96,13 +100,12 @@ void LiveStacksWrapperLegacy::print(raw_ostream &OS, const Module *) const {
 }
 
 /// print - Implement the dump method.
-void LiveStacks::print(raw_ostream &OS, const Module*) const {
+void LiveStacks::print(raw_ostream &OS, const Module *) const {
 
   OS << "********** INTERVALS **********\n";
-  for (const_iterator I = begin(), E = end(); I != E; ++I) {
-    I->second.print(OS);
-    int Slot = I->first;
-    const TargetRegisterClass *RC = getIntervalRegClass(Slot);
+  for (int Idx = 0; Idx < (int)S2LI.size(); ++Idx) {
+    S2LI[Idx]->print(OS);
+    const TargetRegisterClass *RC = S2RC[Idx];
     if (RC)
       OS << " [" << TRI->getRegClassName(RC) << "]\n";
     else
diff --git a/llvm/lib/CodeGen/StackSlotColoring.cpp b/llvm/lib/CodeGen/StackSlotColoring.cpp
index 2f81bea4e86ba..96897fb4b1b44 100644
--- a/llvm/lib/CodeGen/StackSlotColoring.cpp
+++ b/llvm/lib/CodeGen/StackSlotColoring.cpp
@@ -262,24 +262,14 @@ void StackSlotColoring::InitializeSlots() {
   UsedColors[0].resize(LastFI);
   Assignments.resize(LastFI);
 
-  using Pair = std::iterator_traits<LiveStacks::iterator>::value_type;
-
-  SmallVector<Pair *, 16> Intervals;
-
-  Intervals.reserve(LS->getNumIntervals());
-  for (auto &I : *LS)
-    Intervals.push_back(&I);
-  llvm::sort(Intervals,
-             [](Pair *LHS, Pair *RHS) { return LHS->first < RHS->first; });
-
   // Gather all spill slots into a list.
   LLVM_DEBUG(dbgs() << "Spill slot intervals:\n");
-  for (auto *I : Intervals) {
-    LiveInterval &li = I->second;
-    LLVM_DEBUG(li.dump());
-    int FI = li.reg().stackSlotIndex();
-    if (MFI->isDeadObjectIndex(FI))
+  for (auto [Idx, I] : llvm::enumerate(*LS)) {
+    int FI = Idx + LS->getStartIdx();
+    if (!I || MFI->isDeadObjectIndex(FI))
       continue;
+    LiveInterval &li = *I;
+    LLVM_DEBUG(li.dump());
 
     SSIntervals.push_back(&li);
     OrigAlignments[FI] = MFI->getObjectAlign(FI);
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUMarkLastScratchLoad.cpp b/llvm/lib/Target/AMDGPU/AMDGPUMarkLastScratchLoad.cpp
index 9b6bb56c85d24..2dcf695e9c583 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUMarkLastScratchLoad.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUMarkLastScratchLoad.cpp
@@ -102,15 +102,15 @@ bool AMDGPUMarkLastScratchLoad::run(MachineFunction &MF) {
 
   bool Changed = false;
 
-  for (auto &[SS, LI] : *LS) {
-    for (const LiveRange::Segment &Segment : LI.segments) {
+  for (auto *LI : *LS) {
+    for (const LiveRange::Segment &Segment : LI->segments) {
 
       // Ignore segments that run to the end of basic block because in this case
       // slot is still live at the end of it.
       if (Segment.end.isBlock())
         continue;
 
-      const int FrameIndex = LI.reg().stackSlotIndex();
+      const int FrameIndex = LI->reg().stackSlotIndex();
       MachineInstr *LastLoad = nullptr;
 
       MachineInstr *MISegmentEnd = SI->getInstructionFromIndex(Segment.end);

@Ralender Ralender force-pushed the LiveStackUseVectorInsteadOfMap branch from e81ca75 to add2fd5 Compare October 28, 2025 21:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants