[llvm] [AMDGPU] Rewrite SADDR memory ops to VADDR reduce xcnt stalls (PR #190654)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 8 00:02:44 PDT 2026
================
@@ -0,0 +1,330 @@
+//===- SIFixXcntStallSAddrReuse.cpp - Fix xcnt stalls from SADDR reuse ----===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// Convert FLAT global SADDR memory ops to VADDR when the SGPR address pair
+/// would be reused across multiple loads. Runs after SGPR RA (greedy) but
+/// before VirtRegRewriter, so saddr operands are still virtual registers
+/// with physical assignments available in VirtRegMap.
+///
+/// This avoids s_wait_xcnt stalls from XNACK replay hazards on reused.
+//===----------------------------------------------------------------------===//
+
+#include "SIFixXcntStallSAddrReuse.h"
+#include "AMDGPU.h"
+#include "GCNSubtarget.h"
+#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
+#include "SIInstrInfo.h"
+#include "SIRegisterInfo.h"
+#include "Utils/AMDGPUBaseInfo.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/LiveIntervals.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/VirtRegMap.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "si-fix-xcnt-stall-saddr-reuse"
+
+static cl::opt<unsigned> SAddrReuseWindow(
+ "amdgpu-saddr-reuse-window", cl::init(30), cl::Hidden,
+ cl::desc("Number of instructions to search for SAddr redefinition"));
+
+STATISTIC(NumConverted, "Number of SADDR loads converted to VADDR");
+
+namespace {
+
+class SIFixXcntStallSAddrReuse {
+ const SIInstrInfo *TII = nullptr;
+ const SIRegisterInfo *TRI = nullptr;
+ MachineRegisterInfo *MRI = nullptr;
+ LiveIntervals *LIS = nullptr;
+ VirtRegMap *VRM = nullptr;
+
+ MCRegister getPhysForSAddr(Register Reg) const;
+ bool isSAddrRedefined(MachineInstr &MI, Register SAddr);
+ MachineInstr *convertToVAddr(MachineInstr &MI, MachineBasicBlock &MBB,
+ Register &NewAddrReg);
+ bool processMBB(MachineBasicBlock &MBB);
+
+public:
+ SIFixXcntStallSAddrReuse(LiveIntervals *LIS = nullptr,
+ VirtRegMap *VRM = nullptr)
+ : LIS(LIS), VRM(VRM) {}
+ bool run(MachineFunction &MF);
+};
+
+class SIFixXcntStallSAddrReuseLegacy : public MachineFunctionPass {
+public:
+ static char ID;
+ SIFixXcntStallSAddrReuseLegacy() : MachineFunctionPass(ID) {}
+
+ bool runOnMachineFunction(MachineFunction &MF) override {
+ if (skipFunction(MF.getFunction()))
+ return false;
+ if (!MF.getSubtarget<GCNSubtarget>().hasWaitXcnt())
+ return false;
+ auto *LISWrapper = getAnalysisIfAvailable<LiveIntervalsWrapperPass>();
+ LiveIntervals *LIS = LISWrapper ? &LISWrapper->getLIS() : nullptr;
+ auto *VRMWrapper = getAnalysisIfAvailable<VirtRegMapWrapperLegacy>();
+ VirtRegMap *VRM = VRMWrapper ? &VRMWrapper->getVRM() : nullptr;
+ return SIFixXcntStallSAddrReuse(LIS, VRM).run(MF);
+ }
+
+ StringRef getPassName() const override {
+ return "SI Fix Xcnt Stall SAddr Reuse";
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ AU.addUsedIfAvailable<VirtRegMapWrapperLegacy>();
+ AU.addUsedIfAvailable<LiveIntervalsWrapperPass>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+};
+
+} // end anonymous namespace
+
+char SIFixXcntStallSAddrReuseLegacy::ID = 0;
+
+INITIALIZE_PASS(SIFixXcntStallSAddrReuseLegacy, DEBUG_TYPE,
+ "SI Fix Xcnt Stall SAddr Reuse", false, false)
+
+char &llvm::SIFixXcntStallSAddrReuseLegacyID =
+ SIFixXcntStallSAddrReuseLegacy::ID;
+
+PreservedAnalyses
+SIFixXcntStallSAddrReusePass::run(MachineFunction &MF,
+ MachineFunctionAnalysisManager &MFAM) {
+ if (!MF.getSubtarget<GCNSubtarget>().hasWaitXcnt())
+ return PreservedAnalyses::all();
+ auto *LIS = MFAM.getCachedResult<LiveIntervalsAnalysis>(MF);
+ auto *VRM = MFAM.getCachedResult<VirtRegMapAnalysis>(MF);
+ if (!SIFixXcntStallSAddrReuse(LIS, VRM).run(MF))
+ return PreservedAnalyses::all();
+ auto PA = getMachineFunctionPassPreservedAnalyses();
----------------
arsenm wrote:
```suggestion
PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses();
```
https://github.com/llvm/llvm-project/pull/190654
More information about the llvm-commits
mailing list