[llvm] 77513e7 - [SPIRV] Add a `SPIRVTypeInst` type with some guardrails (#179947)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 11 03:30:46 PST 2026
Author: Juan Manuel Martinez CaamaƱo
Date: 2026-02-11T12:30:42+01:00
New Revision: 77513e7d740b37da675eadbc0a80b09624614af6
URL: https://github.com/llvm/llvm-project/commit/77513e7d740b37da675eadbc0a80b09624614af6
DIFF: https://github.com/llvm/llvm-project/commit/77513e7d740b37da675eadbc0a80b09624614af6.diff
LOG: [SPIRV] Add a `SPIRVTypeInst` type with some guardrails (#179947)
The idea behind this PR is to propose a type that we can deploy
gradually to add some guardrails and enforce invariants in the SPIRV
backend.
The PR has 3 commits:
* A first commit where the `SPIRVTypeInst` type is proposed. It's just a
wrapper around `MachineInstr` that adds an assert to check that a
`SPIRVTypeInst` defines a register with the type register class.
* A second commit that shows how the migration could look like for a
single function.
* A third commit that motivates why: we have a `SPIRVType *TypeInst`
that never defines a type in a function whose intention looks very
confusing.
Added:
Modified:
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index b7cfa4f6f2ac1..269e59d9ed82b 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -25,9 +25,64 @@
namespace llvm {
class SPIRVSubtarget;
+/// @deprecated Use SPIRVTypeInst instead
+/// SPIRVType is supposed to represent a MachineInstr that defines a SPIRV Type
+/// (e.g. an OpTypeInt intruction). It is misused in several places and we're
+/// getting rid of it.
using SPIRVType = const MachineInstr;
+
using StructOffsetDecorator = std::function<void(Register)>;
+class SPIRVTypeInst {
+ const MachineInstr *MI;
+
+public:
+ static bool definesATypeRegister(const MachineInstr &MI) {
+ const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
+ return MRI.getRegClass(MI.getOperand(0).getReg()) == &SPIRV::TYPERegClass;
+ }
+
+ SPIRVTypeInst(const MachineInstr &MI) : SPIRVTypeInst(&MI) {}
+ SPIRVTypeInst(const MachineInstr *MI) : MI(MI) {
+ // A SPIRV Type whose result is not a type is invalid.
+ assert(!MI || definesATypeRegister(*MI));
+ }
+
+ // No need to verify the register since it's already verified by the copied
+ // object.
+ SPIRVTypeInst(const SPIRVTypeInst &Other) : MI(Other.MI) {}
+
+ SPIRVTypeInst &operator=(const SPIRVTypeInst &Other) {
+ MI = Other.MI;
+ return *this;
+ }
+
+ const MachineInstr &operator*() const { return *MI; }
+ const MachineInstr *operator->() const { return MI; }
+ operator const MachineInstr *() const { return MI; }
+
+ bool operator==(const SPIRVTypeInst &Other) const { return MI == Other.MI; }
+ bool operator!=(const SPIRVTypeInst &Other) const { return MI != Other.MI; }
+
+ bool operator==(const MachineInstr *Other) const { return MI == Other; }
+ bool operator!=(const MachineInstr *Other) const { return MI != Other; }
+
+ operator bool() const { return MI; }
+
+ unsigned getHashValue() const {
+ return DenseMapInfo<const MachineInstr *>::getHashValue(MI);
+ }
+};
+
+template <> struct DenseMapInfo<SPIRVTypeInst> {
+ static SPIRVTypeInst getEmptyKey() { return SPIRVTypeInst(nullptr); }
+ static SPIRVTypeInst getTombstoneKey() { return SPIRVTypeInst(nullptr); }
+ static unsigned getHashValue(SPIRVTypeInst Ty) { return Ty.getHashValue(); }
+ static bool isEqual(SPIRVTypeInst Ty1, SPIRVTypeInst Ty2) {
+ return Ty1 == Ty2;
+ }
+};
+
class SPIRVGlobalRegistry : public SPIRVIRMapping {
// Registers holding values which have types associated with them.
// Initialized upon VReg definition in IRTranslator.
diff --git a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
index 7d3711a583e50..b16dae012b10d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVISelLowering.cpp
@@ -39,7 +39,8 @@ SPIRVTargetLowering::SPIRVTargetLowering(const TargetMachine &TM,
// Returns true of the types logically match, as defined in
// https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#OpCopyLogical.
-static bool typesLogicallyMatch(const SPIRVType *Ty1, const SPIRVType *Ty2,
+static bool typesLogicallyMatch(const SPIRVTypeInst Ty1,
+ const SPIRVTypeInst Ty2,
SPIRVGlobalRegistry &GR) {
if (Ty1->getOpcode() != Ty2->getOpcode())
return false;
@@ -52,17 +53,19 @@ static bool typesLogicallyMatch(const SPIRVType *Ty1, const SPIRVType *Ty2,
if (Ty1->getOperand(2).getReg() != Ty2->getOperand(2).getReg())
return false;
- SPIRVType *ElemType1 = GR.getSPIRVTypeForVReg(Ty1->getOperand(1).getReg());
- SPIRVType *ElemType2 = GR.getSPIRVTypeForVReg(Ty2->getOperand(1).getReg());
+ SPIRVTypeInst ElemType1 =
+ GR.getSPIRVTypeForVReg(Ty1->getOperand(1).getReg());
+ SPIRVTypeInst ElemType2 =
+ GR.getSPIRVTypeForVReg(Ty2->getOperand(1).getReg());
return ElemType1 == ElemType2 ||
typesLogicallyMatch(ElemType1, ElemType2, GR);
}
if (Ty1->getOpcode() == SPIRV::OpTypeStruct) {
for (unsigned I = 1; I < Ty1->getNumOperands(); I++) {
- SPIRVType *ElemType1 =
+ SPIRVTypeInst ElemType1 =
GR.getSPIRVTypeForVReg(Ty1->getOperand(I).getReg());
- SPIRVType *ElemType2 =
+ SPIRVTypeInst ElemType2 =
GR.getSPIRVTypeForVReg(Ty2->getOperand(I).getReg());
if (ElemType1 != ElemType2 &&
!typesLogicallyMatch(ElemType1, ElemType2, GR))
More information about the llvm-commits
mailing list