Skip to content

Conversation

arsenm
Copy link
Contributor

@arsenm arsenm commented Aug 27, 2025

This loop over all the operands in the MachineInstr will eventually
go past the end of the MCInstrDesc's explicit operands. We don't
need the instr desc to compute the constant bus usage, just the
register and whether it's implicit or not. The check here is slightly
conservative. e.g. a random vcc implicit use appended to an instruction
will falsely report a constant bus use.

@llvmbot
Copy link
Member

llvmbot commented Aug 27, 2025

@llvm/pr-subscribers-backend-amdgpu

Author: Matt Arsenault (arsenm)

Changes

This loop over all the operands in the MachineInstr will eventually
go past the end of the MCInstrDesc's explicit operands. We don't
need the instr desc to compute the constant bus usage, just the
register and whether it's implicit or not. The check here is slightly
conservative. e.g. a random vcc implicit use appended to an instruction
will falsely report a constant bus use.


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

2 Files Affected:

  • (modified) llvm/lib/Target/AMDGPU/SIInstrInfo.cpp (+40-24)
  • (modified) llvm/lib/Target/AMDGPU/SIInstrInfo.h (+4)
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index ac60dc19aa974..d3c8e8ad7c02e 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -4758,6 +4758,36 @@ MachineInstr *SIInstrInfo::buildShrunkInst(MachineInstr &MI,
   return Inst32;
 }
 
+bool SIInstrInfo::physRegUsesConstantBus(const MachineOperand &RegOp) const {
+  // Null is free
+  Register Reg = RegOp.getReg();
+  if (Reg == AMDGPU::SGPR_NULL || Reg == AMDGPU::SGPR_NULL64)
+    return false;
+
+  // SGPRs use the constant bus
+
+  // FIXME: implicit registers that are not part of the MCInstrDesc's implicit
+  // physical register operands should also count.
+  if (RegOp.isImplicit())
+    return Reg == AMDGPU::VCC || Reg == AMDGPU::VCC_LO || Reg == AMDGPU::M0;
+
+  // Normal exec read does not count.
+  if ((Reg == AMDGPU::EXEC || Reg == AMDGPU::EXEC_LO) && RegOp.isImplicit())
+    return false;
+
+  // SGPRs use the constant bus
+  return AMDGPU::SReg_32RegClass.contains(Reg) ||
+         AMDGPU::SReg_64RegClass.contains(Reg);
+}
+
+bool SIInstrInfo::regUsesConstantBus(const MachineOperand &RegOp,
+                                     const MachineRegisterInfo &MRI) const {
+  Register Reg = RegOp.getReg();
+  if (Reg.isVirtual())
+    return RI.isSGPRClass(MRI.getRegClass(Reg));
+  return physRegUsesConstantBus(RegOp);
+}
+
 bool SIInstrInfo::usesConstantBus(const MachineRegisterInfo &MRI,
                                   const MachineOperand &MO,
                                   const MCOperandInfo &OpInfo) const {
@@ -4765,23 +4795,10 @@ bool SIInstrInfo::usesConstantBus(const MachineRegisterInfo &MRI,
   if (!MO.isReg())
     return !isInlineConstant(MO, OpInfo);
 
-  if (!MO.isUse())
-    return false;
-
-  if (MO.getReg().isVirtual())
-    return RI.isSGPRClass(MRI.getRegClass(MO.getReg()));
-
-  // Null is free
-  if (MO.getReg() == AMDGPU::SGPR_NULL || MO.getReg() == AMDGPU::SGPR_NULL64)
-    return false;
-
-  // SGPRs use the constant bus
-  if (MO.isImplicit()) {
-    return MO.getReg() == AMDGPU::M0 || MO.getReg() == AMDGPU::VCC ||
-           MO.getReg() == AMDGPU::VCC_LO;
-  }
-  return AMDGPU::SReg_32RegClass.contains(MO.getReg()) ||
-         AMDGPU::SReg_64RegClass.contains(MO.getReg());
+  Register Reg = MO.getReg();
+  if (Reg.isVirtual())
+    return RI.isSGPRClass(MRI.getRegClass(Reg));
+  return physRegUsesConstantBus(MO);
 }
 
 static Register findImplicitSGPRRead(const MachineInstr &MI) {
@@ -6250,13 +6267,12 @@ bool SIInstrInfo::isOperandLegal(const MachineInstr &MI, unsigned OpIdx,
         continue;
       const MachineOperand &Op = MI.getOperand(i);
       if (Op.isReg()) {
-        RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
-        if (!SGPRsUsed.count(SGPR) &&
-            // FIXME: This can access off the end of the operands() array.
-            usesConstantBus(MRI, Op, InstDesc.operands().begin()[i])) {
-          if (--ConstantBusLimit <= 0)
-            return false;
-          SGPRsUsed.insert(SGPR);
+        if (Op.isUse()) {
+          RegSubRegPair SGPR(Op.getReg(), Op.getSubReg());
+          if (regUsesConstantBus(Op, MRI) && SGPRsUsed.insert(SGPR).second) {
+            if (--ConstantBusLimit <= 0)
+              return false;
+          }
         }
       } else if (AMDGPU::isSISrcOperand(InstDesc, i) &&
                  !isInlineConstant(Op, InstDesc.operands()[i])) {
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
index 7552ead12570f..9482b91350d80 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
@@ -1189,6 +1189,10 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo {
   /// This function will return false if you pass it a 32-bit instruction.
   bool hasVALU32BitEncoding(unsigned Opcode) const;
 
+  bool physRegUsesConstantBus(const MachineOperand &Reg) const;
+  bool regUsesConstantBus(const MachineOperand &Reg,
+                          const MachineRegisterInfo &MRI) const;
+
   /// Returns true if this operand uses the constant bus.
   bool usesConstantBus(const MachineRegisterInfo &MRI,
                        const MachineOperand &MO,

@arsenm arsenm force-pushed the users/arsenm/amdgpu/dpp-avoid-isOperandLegal-incomplete-instruction branch from 088e57a to 11df2dc Compare August 27, 2025 13:39
@arsenm arsenm force-pushed the users/arsenm/amdgpu/fix-oob-constant-bus-check branch from e16231a to 3aaf3b7 Compare August 27, 2025 13:39
return false;

// SGPRs use the constant bus
return AMDGPU::SReg_32RegClass.contains(Reg) ||
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isSGPRPhysReg()? Just in case we will have more classes, or got ttmp or something like that in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate change, this just shuffles the existing logic

@arsenm arsenm force-pushed the users/arsenm/amdgpu/dpp-avoid-isOperandLegal-incomplete-instruction branch from 11df2dc to b8551c4 Compare September 2, 2025 14:26
@arsenm arsenm force-pushed the users/arsenm/amdgpu/fix-oob-constant-bus-check branch from 3aaf3b7 to a2bb311 Compare September 2, 2025 14:26
@arsenm arsenm force-pushed the users/arsenm/amdgpu/dpp-avoid-isOperandLegal-incomplete-instruction branch from b8551c4 to 8867ca0 Compare September 2, 2025 15:38
@arsenm arsenm force-pushed the users/arsenm/amdgpu/fix-oob-constant-bus-check branch from a2bb311 to 249e2ec Compare September 2, 2025 15:38
Base automatically changed from users/arsenm/amdgpu/dpp-avoid-isOperandLegal-incomplete-instruction to main September 2, 2025 16:19
@arsenm
Copy link
Contributor Author

arsenm commented Sep 2, 2025

ping

This loop over all the operands in the MachineInstr will eventually
go past the end of the MCInstrDesc's explicit operands. We don't
need the instr desc to compute the constant bus usage, just the
register and whether it's implicit or not. The check here is slightly
conservative. e.g. a random vcc implicit use appended to an instruction
will falsely report a constant bus use.
@arsenm arsenm force-pushed the users/arsenm/amdgpu/fix-oob-constant-bus-check branch from 249e2ec to ec7dbe2 Compare September 2, 2025 16:49
@arsenm arsenm enabled auto-merge (squash) September 2, 2025 16:55
@arsenm arsenm merged commit d6a72cb into main Sep 2, 2025
9 checks passed
@arsenm arsenm deleted the users/arsenm/amdgpu/fix-oob-constant-bus-check branch September 2, 2025 17:25
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.

5 participants