[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