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