[llvm] [AMDGPU] Introduce Next-Use Analysis for SSA-based Register Allocation (PR #156079)
Nicolai Hähnle via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 8 09:12:28 PST 2025
================
@@ -0,0 +1,448 @@
+//===- AMDGPUNextUseAnalysis.h ----------------------------------------*- C++-
+//*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_AMDGPU_NEXT_USE_ANALYSIS_H
+#define LLVM_LIB_TARGET_AMDGPU_NEXT_USE_ANALYSIS_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/CodeGen/SlotIndexes.h"
+
+#include "AMDGPUSSARAUtils.h"
+#include "GCNSubtarget.h"
+#include "SIRegisterInfo.h"
+#include "VRegMaskPair.h"
+
+#include <algorithm>
+#include <limits>
+#include <set>
+
+using namespace llvm;
+
+// namespace {
+
+// Helper function for rebasing successor distances into current block frame
+static inline int64_t rebaseFromSucc(int64_t succStored, unsigned succEntryOff,
+ int64_t edgeWeight /*0 or LoopTag*/) {
+ // Move succ-relative value into "current block end" frame.
+ return (int64_t)succStored + (int64_t)succEntryOff + (int64_t)edgeWeight;
+}
+
+class NextUseResult {
+ friend class AMDGPUNextUseAnalysisWrapper;
+ SlotIndexes *Indexes;
+ const MachineRegisterInfo *MRI;
+ const SIRegisterInfo *TRI;
+ MachineLoopInfo *LI;
+
+ TimerGroup *TG;
+ Timer *T1;
+ Timer *T2;
+
+ class VRegDistances {
+
+ using Record = std::pair<LaneBitmask, int64_t>;
+ struct CompareByDist {
+ bool operator()(const Record &LHS, const Record &RHS) const {
+ if (LHS.second != RHS.second) // Different distances
+ return LHS.second < RHS.second; // Closest first
+ return LHS.first.getAsInteger() <
+ RHS.first.getAsInteger(); // Tiebreaker
+ }
+ };
+
+ public:
+ using SortedRecords = std::set<Record, CompareByDist>;
+
+ private:
+ DenseMap<unsigned, SortedRecords> NextUseMap;
+
+ public:
+ auto begin() { return NextUseMap.begin(); }
+ auto end() { return NextUseMap.end(); }
+
+ auto begin() const { return NextUseMap.begin(); }
+ auto end() const { return NextUseMap.end(); }
+
+ size_t size() const { return NextUseMap.size(); }
+ std::pair<bool, SortedRecords> get(unsigned Key) const {
+ if (NextUseMap.contains(Key))
+ return {true, NextUseMap.find(Key)->second};
+ return {false, SortedRecords()};
+ }
+
+ SortedRecords &operator[](unsigned Key) { return NextUseMap[Key]; }
+
+ SmallVector<unsigned> keys() {
+ SmallVector<unsigned> Keys;
+ for (auto P : NextUseMap)
+ Keys.push_back(P.first);
+ return Keys;
+ }
+
+ bool contains(unsigned Key) { return NextUseMap.contains(Key); }
+
+ bool insert(VRegMaskPair VMP, int64_t Dist) {
+ Record R(VMP.getLaneMask(), Dist);
+ if (NextUseMap.contains(VMP.getVReg())) {
+ SortedRecords &Dists = NextUseMap[VMP.getVReg()];
+
+ if (Dists.find(R) == Dists.end()) {
+ SmallVector<SortedRecords::iterator, 4> ToErase;
+
+ for (auto It = Dists.begin(); It != Dists.end(); ++It) {
+ const Record &D = *It;
+
+ // Check if existing use covers the new use
+ if ((R.first & D.first) == R.first) {
+ // Existing use covers new use
+ if (D.second <= R.second) {
+ // Existing use is closer or equal → reject new use
+ return false;
+ }
+ // Existing use is further → continue (might replace it)
+ }
+
+ // Check if new use covers existing use
+ if ((D.first & R.first) == D.first) {
+ // New use covers existing use
+ if (R.second <= D.second) {
+ // New use is closer → mark existing for removal
----------------
nhaehnle wrote:
Indeed.
https://github.com/llvm/llvm-project/pull/156079
More information about the llvm-commits
mailing list