[llvm] [SPIRV] Add reads from image buffer for shaders. (PR #115178)
Steven Perron via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 12 07:14:08 PST 2024
https://github.com/s-perron updated https://github.com/llvm/llvm-project/pull/115178
>From e7960fc17526cff9d7ccd7acbd8dc8a5da662b5c Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenperron at google.com>
Date: Fri, 20 Sep 2024 11:02:12 -0400
Subject: [PATCH 1/7] [SPIRV] Add reads from image buffer for shaders.
This commit adds an intrinsic that will read from an image buffer. We
chose to match the name of the DXIL intrinsic for simplicity in clang.
We cannot reuse the existing openCL readimage function because that is
not a reserved name in HLSL.
I considered trying to refactor generateReadImageInst, so that we could
share code between the two implementations. However, most of the code in
generateReadImageInst is concerned with trying to figure out which type
of image read is being done. Once we factor out the code that will be
common, then we end up with just a single call to the MIRBuilder being
common.
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 6 +
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 20 ++++
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h | 9 ++
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 108 ++++++++++++++++++
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 20 ++++
.../SPIRV/hlsl-resources/BufferLoad.ll | 66 +++++++++++
...lslBufferLoad.ll => ScalarResourceType.ll} | 0
.../SPIRV/hlsl-resources/UnknownBufferLoad.ll | 30 +++++
8 files changed, 259 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-resources/BufferLoad.ll
rename llvm/test/CodeGen/SPIRV/hlsl-resources/{HlslBufferLoad.ll => ScalarResourceType.ll} (100%)
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-resources/UnknownBufferLoad.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index e93d6fa83de61b..00110bb024385f 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -102,4 +102,10 @@ let TargetPrefix = "spv" in {
[IntrNoMem]>;
def int_spv_firstbituhigh : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_anyint_ty], [IntrNoMem]>;
def int_spv_firstbitshigh : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i32_ty>], [llvm_anyint_ty], [IntrNoMem]>;
+
+ // Read a value from the image buffer. It does not translate directly to a
+ // single OpImageRead because the result type is not necessarily a 4 element
+ // vector.
+ def int_spv_typedBufferLoad
+ : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty, llvm_i32_ty]>;
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index f66506beaa6ed6..694497f9e68675 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -1056,6 +1056,11 @@ SPIRVGlobalRegistry::getSPIRVTypeForVReg(Register VReg,
return nullptr;
}
+SPIRVType *SPIRVGlobalRegistry::getResultType(Register VReg) {
+ MachineInstr *Instr = CurMF->getRegInfo().getVRegDef(VReg);
+ return getSPIRVTypeForVReg(Instr->getOperand(1).getReg());
+}
+
SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(
const Type *Ty, MachineIRBuilder &MIRBuilder,
SPIRV::AccessQualifier::AccessQualifier AccessQual, bool EmitIR) {
@@ -1126,6 +1131,21 @@ SPIRVGlobalRegistry::getScalarOrVectorComponentCount(SPIRVType *Type) const {
: 1;
}
+SPIRVType *
+SPIRVGlobalRegistry::getScalarOrVectorComponentType(Register VReg) const {
+ return getScalarOrVectorComponentType(getSPIRVTypeForVReg(VReg));
+}
+
+SPIRVType *
+SPIRVGlobalRegistry::getScalarOrVectorComponentType(SPIRVType *Type) const {
+ if (!Type)
+ return nullptr;
+ Register ScalarReg = Type->getOpcode() == SPIRV::OpTypeVector
+ ? Type->getOperand(1).getReg()
+ : Type->getOperand(0).getReg();
+ return getSPIRVTypeForVReg(ScalarReg);
+}
+
unsigned
SPIRVGlobalRegistry::getScalarOrVectorBitWidth(const SPIRVType *Type) const {
assert(Type && "Invalid Type pointer");
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index a95b488960c4c3..0cf174d0e45afa 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -353,6 +353,9 @@ class SPIRVGlobalRegistry {
SPIRVType *getSPIRVTypeForVReg(Register VReg,
const MachineFunction *MF = nullptr) const;
+ // Return the result type of the instruction defining the register.
+ SPIRVType *getResultType(Register VReg);
+
// Whether the given VReg has a SPIR-V type mapped to it yet.
bool hasSPIRVTypeForVReg(Register VReg) const {
return getSPIRVTypeForVReg(VReg) != nullptr;
@@ -388,6 +391,12 @@ class SPIRVGlobalRegistry {
unsigned getScalarOrVectorComponentCount(Register VReg) const;
unsigned getScalarOrVectorComponentCount(SPIRVType *Type) const;
+ // Return the component type in a vector if the argument is associated with
+ // a vector type. Returns the argument itself for a scalar type, and nullptr
+ // for a missing type.
+ SPIRVType *getScalarOrVectorComponentType(Register VReg) const;
+ SPIRVType *getScalarOrVectorComponentType(SPIRVType *Type) const;
+
// For vectors or scalars of booleans, integers and floats, return the scalar
// type's bitwidth. Otherwise calls llvm_unreachable().
unsigned getScalarOrVectorBitWidth(const SPIRVType *Type) const;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 414583aea91e64..c3b1122769813f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -264,6 +264,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
void selectHandleFromBinding(Register &ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
+ void selectReadImageIntrinsic(Register &ResVReg, const SPIRVType *ResType,
+ MachineInstr &I) const;
+
// Utilities
Register buildI32Constant(uint32_t Val, MachineInstr &I,
const SPIRVType *ResType = nullptr) const;
@@ -288,6 +291,12 @@ class SPIRVInstructionSelector : public InstructionSelector {
uint32_t Binding, uint32_t ArraySize,
Register IndexReg, bool IsNonUniform,
MachineIRBuilder MIRBuilder) const;
+ SPIRVType *getCorrespondingVec4Type(const SPIRVType *Type,
+ MachineInstr &I) const;
+ void extractScalarOrVectorFromVector(Register &ResultReg,
+ const SPIRVType *ResType,
+ Register &InputReg,
+ MachineInstr &InsertionPoint) const;
};
} // end anonymous namespace
@@ -2767,6 +2776,10 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
selectHandleFromBinding(ResVReg, ResType, I);
return true;
}
+ case Intrinsic::spv_typedBufferLoad: {
+ selectReadImageIntrinsic(ResVReg, ResType, I);
+ return true;
+ }
default: {
std::string DiagMsg;
raw_string_ostream OS(DiagMsg);
@@ -2803,6 +2816,83 @@ void SPIRVInstructionSelector::selectHandleFromBinding(Register &ResVReg,
.addUse(VarReg);
}
+void SPIRVInstructionSelector::selectReadImageIntrinsic(
+ Register &ResVReg, const SPIRVType *ResType, MachineInstr &I) const {
+
+ // If the load of the image is in a different basic block, then
+ // this will generate invalid code. A proper solution is to move
+ // the OpLoad from selectHandleFromBinding here. However, to do
+ // that we will need to change the return type of the intrinsic.
+ // We will do that when we can, but for now trying to move forward with other
+ // issues.
+ Register ImageReg = I.getOperand(2).getReg();
+
+ SPIRVType *ReadType = getCorrespondingVec4Type(ResType, I);
+ Register ReadReg = MRI->createVirtualRegister(GR.getRegClass(ReadType));
+ BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpImageRead))
+ .addDef(ReadReg)
+ .addUse(GR.getSPIRVTypeID(ReadType))
+ .addUse(ImageReg)
+ .addUse(I.getOperand(3).getReg());
+
+ extractScalarOrVectorFromVector(ResVReg, ResType, ReadReg, I);
+}
+
+void SPIRVInstructionSelector::extractScalarOrVectorFromVector(
+ Register &ResultReg, const SPIRVType *ResType, Register &InputReg,
+ MachineInstr &InsertionPoint) const {
+ SPIRVType *InputType = GR.getResultType(InputReg);
+ assert(InputType->getOpcode() == SPIRV::OpTypeVector);
+
+ if (ResType->getOpcode() != SPIRV::OpTypeVector) {
+ assert(ResType == GR.getScalarOrVectorComponentType(InputType));
+ BuildMI(*InsertionPoint.getParent(), InsertionPoint,
+ InsertionPoint.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
+ .addDef(ResultReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(InputReg)
+ .addImm(0);
+ return;
+ }
+
+ uint64_t InputSize = GR.getScalarOrVectorComponentCount(InputType);
+ uint64_t VectorSize = GR.getScalarOrVectorComponentCount(ResType);
+ if (VectorSize == InputSize) {
+ BuildMI(*InsertionPoint.getParent(), InsertionPoint,
+ InsertionPoint.getDebugLoc(), TII.get(SPIRV::OpCopyObject))
+ .addDef(ResultReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(InputReg);
+ return;
+ }
+
+ assert(VectorSize < InputSize &&
+ "Cannot extract more element than there are in the input.");
+ SmallVector<Register> ComponentRegisters;
+ SPIRVType *ScalarType = GR.getScalarOrVectorComponentType(ResType);
+ const TargetRegisterClass *ScalarRegClass = GR.getRegClass(ScalarType);
+ for (uint64_t i = 0; i < VectorSize; i++) {
+ Register ComponentReg = MRI->createVirtualRegister(ScalarRegClass);
+ BuildMI(*InsertionPoint.getParent(), InsertionPoint,
+ InsertionPoint.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
+ .addDef(ComponentReg)
+ .addUse(ScalarType->getOperand(0).getReg())
+ .addUse(InputReg)
+ .addImm(i);
+ ComponentRegisters.emplace_back(ComponentReg);
+ }
+
+ MachineInstrBuilder MIB = BuildMI(*InsertionPoint.getParent(), InsertionPoint,
+ InsertionPoint.getDebugLoc(),
+ TII.get(SPIRV::OpCompositeConstruct))
+ .addDef(ResultReg)
+ .addUse(GR.getSPIRVTypeID(ResType));
+
+ for (Register ComponentReg : ComponentRegisters) {
+ MIB.addUse(ComponentReg);
+ }
+}
+
Register SPIRVInstructionSelector::buildPointerToResource(
const SPIRVType *ResType, uint32_t Set, uint32_t Binding,
uint32_t ArraySize, Register IndexReg, bool IsNonUniform,
@@ -3305,6 +3395,24 @@ bool SPIRVInstructionSelector::selectSpvThreadId(Register ResVReg,
return MIB.constrainAllUses(TII, TRI, RBI);
}
+SPIRVType *
+SPIRVInstructionSelector::getCorrespondingVec4Type(const SPIRVType *Type,
+ MachineInstr &I) const {
+ MachineIRBuilder MIRBuilder(I);
+ if (Type->getOpcode() != SPIRV::OpTypeVector) {
+ return GR.getOrCreateSPIRVVectorType(Type, 4, MIRBuilder);
+ }
+
+ uint64_t VectorSize = Type->getOperand(2).getImm();
+ if (VectorSize == 4) {
+ return Type;
+ }
+
+ Register ScalarTypeReg = Type->getOperand(1).getReg();
+ const SPIRVType *ScalarType = GR.getSPIRVTypeForVReg(ScalarTypeReg);
+ return GR.getOrCreateSPIRVVectorType(ScalarType, 4, MIRBuilder);
+}
+
namespace llvm {
InstructionSelector *
createSPIRVInstructionSelector(const SPIRVTargetMachine &TM,
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index e8641b3a105dec..673fde96ea19fd 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -719,6 +719,11 @@ void RequirementHandler::initAvailableCapabilitiesForVulkan(
Capability::UniformTexelBufferArrayNonUniformIndexingEXT,
Capability::StorageTexelBufferArrayNonUniformIndexingEXT});
}
+
+ // Became core in Vulkan 1.3
+ if (ST.isAtLeastSPIRVVer(VersionTuple(1, 6))) {
+ addAvailableCaps({Capability::StorageImageReadWithoutFormat});
+ }
}
} // namespace SPIRV
@@ -1005,6 +1010,13 @@ void addOpAccessChainReqs(const MachineInstr &Instr,
}
}
+static bool imageTypeHasUnknownFormat(SPIRVType *TypeInst) {
+ if (TypeInst->getOpcode() != SPIRV::OpTypeImage)
+ return false;
+ assert(TypeInst->getOperand(7).isImm() && "The image format must be an imm.");
+ return TypeInst->getOperand(7).getImm() == 0;
+}
+
static void AddDotProductRequirements(const MachineInstr &MI,
SPIRV::RequirementHandler &Reqs,
const SPIRVSubtarget &ST) {
@@ -1411,6 +1423,14 @@ void addInstrRequirements(const MachineInstr &MI,
case SPIRV::OpUDot:
AddDotProductRequirements(MI, Reqs, ST);
break;
+ case SPIRV::OpImageRead: {
+ Register ImageReg = MI.getOperand(2).getReg();
+ SPIRVType *TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(ImageReg);
+ if (imageTypeHasUnknownFormat(TypeDef))
+ Reqs.addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
+ break;
+ }
+
default:
break;
}
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/BufferLoad.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/BufferLoad.ll
new file mode 100644
index 00000000000000..27c66eeb238a10
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/BufferLoad.ll
@@ -0,0 +1,66 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-vulkan-library %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-vulkan-library %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-NOT: OpCapability StorageImageReadWithoutFormat
+
+; CHECK-DAG: OpDecorate [[IntBufferVar:%[0-9]+]] DescriptorSet 16
+; CHECK-DAG: OpDecorate [[IntBufferVar]] Binding 7
+
+; CHECK-DAG: [[int:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[zero:%[0-9]+]] = OpConstant [[int]] 0
+; CHECK-DAG: [[v4_int:%[0-9]+]] = OpTypeVector [[int]] 4
+; CHECK-DAG: [[v2_int:%[0-9]+]] = OpTypeVector [[int]] 2
+; CHECK-DAG: [[RWBufferTypeInt:%[0-9]+]] = OpTypeImage [[int]] Buffer 2 0 0 2 R32i {{$}}
+; CHECK-DAG: [[IntBufferPtrType:%[0-9]+]] = OpTypePointer UniformConstant [[RWBufferTypeInt]]
+; CHECK-DAG: [[IntBufferVar]] = OpVariable [[IntBufferPtrType]] UniformConstant
+
+; CHECK: {{%[0-9]+}} = OpFunction {{%[0-9]+}} DontInline {{%[0-9]+}}
+; CHECK-NEXT: OpLabel
+define void @RWBufferLoad_Vec4_I32() #0 {
+; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
+ %buffer0 = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 24)
+ @llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_24(
+ i32 16, i32 7, i32 1, i32 0, i1 false)
+
+; CHECK: OpImageRead [[v4_int]] [[buffer]] [[zero]]
+ %data0 = call <4 x i32> @llvm.spv.typedBufferLoad(
+ target("spirv.Image", i32, 5, 2, 0, 0, 2, 24) %buffer0, i32 0)
+
+ ret void
+}
+
+; CHECK: {{%[0-9]+}} = OpFunction {{%[0-9]+}} DontInline {{%[0-9]+}}
+; CHECK-NEXT: OpLabel
+define void @RWBufferLoad_I32() #0 {
+; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
+ %buffer1 = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 24)
+ @llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_24(
+ i32 16, i32 7, i32 1, i32 0, i1 false)
+
+; CHECK: [[V:%[0-9]+]] = OpImageRead [[v4_int]] [[buffer]] [[zero]]
+; CHECK: OpCompositeExtract [[int]] [[V]] 0
+ %data1 = call i32 @llvm.spv.typedBufferLoad(
+ target("spirv.Image", i32, 5, 2, 0, 0, 2, 24) %buffer1, i32 0)
+
+ ret void
+}
+
+; CHECK: {{%[0-9]+}} = OpFunction {{%[0-9]+}} DontInline {{%[0-9]+}}
+; CHECK-NEXT: OpLabel
+define void @RWBufferLoad_Vec2_I32() #0 {
+; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
+ %buffer0 = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 24)
+ @llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_24(
+ i32 16, i32 7, i32 1, i32 0, i1 false)
+
+; CHECK: [[V:%[0-9]+]] = OpImageRead [[v4_int]] [[buffer]] [[zero]]
+; CHECK: [[e0:%[0-9]+]] = OpCompositeExtract [[int]] [[V]] 0
+; CHECK: [[e1:%[0-9]+]] = OpCompositeExtract [[int]] [[V]] 1
+; CHECK: OpCompositeConstruct [[v2_int]] [[e0]] [[e1]]
+ %data0 = call <2 x i32> @llvm.spv.typedBufferLoad(
+ target("spirv.Image", i32, 5, 2, 0, 0, 2, 24) %buffer0, i32 0)
+
+ ret void
+}
+
+attributes #0 = { convergent noinline norecurse "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/HlslBufferLoad.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/ScalarResourceType.ll
similarity index 100%
rename from llvm/test/CodeGen/SPIRV/hlsl-resources/HlslBufferLoad.ll
rename to llvm/test/CodeGen/SPIRV/hlsl-resources/ScalarResourceType.ll
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/UnknownBufferLoad.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/UnknownBufferLoad.ll
new file mode 100644
index 00000000000000..7f9c6f7da2859e
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/UnknownBufferLoad.ll
@@ -0,0 +1,30 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv1.6-vulkan1.3-library %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv1.6-vulkan1.3-library %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: OpCapability StorageImageReadWithoutFormat
+; CHECK-DAG: OpDecorate [[IntBufferVar:%[0-9]+]] DescriptorSet 16
+; CHECK-DAG: OpDecorate [[IntBufferVar]] Binding 7
+
+; CHECK-DAG: [[int:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[zero:%[0-9]+]] = OpConstant [[int]] 0
+; CHECK-DAG: [[v4_int:%[0-9]+]] = OpTypeVector [[int]] 4
+; CHECK-DAG: [[RWBufferTypeInt:%[0-9]+]] = OpTypeImage [[int]] Buffer 2 0 0 2 Unknown {{$}}
+; CHECK-DAG: [[IntBufferPtrType:%[0-9]+]] = OpTypePointer UniformConstant [[RWBufferTypeInt]]
+; CHECK-DAG: [[IntBufferVar]] = OpVariable [[IntBufferPtrType]] UniformConstant
+
+; CHECK: {{%[0-9]+}} = OpFunction {{%[0-9]+}} DontInline {{%[0-9]+}}
+; CHECK-NEXT: OpLabel
+define void @RWBufferLoad_Vec4_I32() #0 {
+; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
+ %buffer0 = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 0)
+ @llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_0(
+ i32 16, i32 7, i32 1, i32 0, i1 false)
+
+; CHECK: OpImageRead [[v4_int]] [[buffer]] [[zero]]
+ %data0 = call <4 x i32> @llvm.spv.typedBufferLoad(
+ target("spirv.Image", i32, 5, 2, 0, 0, 2, 0) %buffer0, i32 0)
+
+ ret void
+}
+
+attributes #0 = { convergent noinline norecurse "frame-pointer"="all" "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
>From a967997a355b66991857a718c30aee21d910c5f2 Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenperron at google.com>
Date: Wed, 6 Nov 2024 15:57:35 -0500
Subject: [PATCH 2/7] Update SpirvUsage.rst.
---
llvm/docs/SPIRVUsage.rst | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/llvm/docs/SPIRVUsage.rst b/llvm/docs/SPIRVUsage.rst
index 0fcaa366c8a3e0..277b9c15292c53 100644
--- a/llvm/docs/SPIRVUsage.rst
+++ b/llvm/docs/SPIRVUsage.rst
@@ -392,6 +392,14 @@ SPIR-V backend, along with their descriptions and argument details.
If `arraySize > 1`, then the binding represents an array of resources\
of the given size, and the handle for the resource at the given index is returned.\
If the index is possibly non-uniform, then `isUniformIndex` must get set to true.
+ * - `int_spv_typeBufferLoad`
+ - Scalar or vector
+ - `[spirv.Image ImageBuffer, 32-bit Integer coordinate]`
+ - Loads a value from a Vulkan image buffer at the given coordinate. The \
+ image buffer data is assumed to be stored as a 4-element vector. If the \
+ return type is a scalar, then the first element of the vector is \
+ returned. If the return type is an n-element vector, then the first \
+ n-elements of the 4-element vector are returned.
.. _spirv-builtin-functions:
>From 97dc974e6d1ba9287a7314d9084e7ac4ed19113e Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenperron at google.com>
Date: Wed, 6 Nov 2024 15:59:09 -0500
Subject: [PATCH 3/7] Small test fix.
---
llvm/test/CodeGen/SPIRV/hlsl-resources/BufferLoad.ll | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/BufferLoad.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/BufferLoad.ll
index 27c66eeb238a10..c2749d13c214d2 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-resources/BufferLoad.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/BufferLoad.ll
@@ -19,7 +19,7 @@
define void @RWBufferLoad_Vec4_I32() #0 {
; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
%buffer0 = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 24)
- @llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_24(
+ @llvm.spv.handle.fromBinding.tspirv.Image_i32_5_2_0_0_2_24(
i32 16, i32 7, i32 1, i32 0, i1 false)
; CHECK: OpImageRead [[v4_int]] [[buffer]] [[zero]]
@@ -34,7 +34,7 @@ define void @RWBufferLoad_Vec4_I32() #0 {
define void @RWBufferLoad_I32() #0 {
; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
%buffer1 = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 24)
- @llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_24(
+ @llvm.spv.handle.fromBinding.tspirv.Image_i32_5_2_0_0_2_24(
i32 16, i32 7, i32 1, i32 0, i1 false)
; CHECK: [[V:%[0-9]+]] = OpImageRead [[v4_int]] [[buffer]] [[zero]]
@@ -50,7 +50,7 @@ define void @RWBufferLoad_I32() #0 {
define void @RWBufferLoad_Vec2_I32() #0 {
; CHECK: [[buffer:%[0-9]+]] = OpLoad [[RWBufferTypeInt]] [[IntBufferVar]]
%buffer0 = call target("spirv.Image", i32, 5, 2, 0, 0, 2, 24)
- @llvm.spv.handle.fromBinding.tspirv.Image_f32_5_2_0_0_2_24(
+ @llvm.spv.handle.fromBinding.tspirv.Image_i32_5_2_0_0_2_24(
i32 16, i32 7, i32 1, i32 0, i1 false)
; CHECK: [[V:%[0-9]+]] = OpImageRead [[v4_int]] [[buffer]] [[zero]]
>From c55851397210400e250e742536c2188747a6ca6f Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenperron at google.com>
Date: Thu, 7 Nov 2024 11:24:14 -0500
Subject: [PATCH 4/7] Fix OpenCL tests.
They require an extra capability.
---
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 3 ++-
llvm/test/CodeGen/SPIRV/read_image.ll | 2 ++
llvm/test/CodeGen/SPIRV/transcoding/OpImageReadMS.ll | 1 +
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 673fde96ea19fd..6cddddd95ffc24 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -660,7 +660,8 @@ void RequirementHandler::initAvailableCapabilitiesForOpenCL(
// Add the min requirements for different OpenCL and SPIR-V versions.
addAvailableCaps({Capability::Addresses, Capability::Float16Buffer,
Capability::Kernel, Capability::Vector16,
- Capability::Groups, Capability::GenericPointer});
+ Capability::Groups, Capability::GenericPointer,
+ Capability::StorageImageReadWithoutFormat});
if (ST.hasOpenCLFullProfile())
addAvailableCaps({Capability::Int64, Capability::Int64Atomics});
if (ST.hasOpenCLImageSupport()) {
diff --git a/llvm/test/CodeGen/SPIRV/read_image.ll b/llvm/test/CodeGen/SPIRV/read_image.ll
index ede5994279d2ff..20063aa6b8b75e 100644
--- a/llvm/test/CodeGen/SPIRV/read_image.ll
+++ b/llvm/test/CodeGen/SPIRV/read_image.ll
@@ -1,5 +1,7 @@
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; CHECK-SPIRV: OpCapability StorageImageReadWithoutFormat
+
; CHECK-SPIRV: %[[#IntTy:]] = OpTypeInt
; CHECK-SPIRV: %[[#IVecTy:]] = OpTypeVector %[[#IntTy]]
; CHECK-SPIRV: %[[#FloatTy:]] = OpTypeFloat
diff --git a/llvm/test/CodeGen/SPIRV/transcoding/OpImageReadMS.ll b/llvm/test/CodeGen/SPIRV/transcoding/OpImageReadMS.ll
index f4e34c325e6013..4de79a24e21363 100644
--- a/llvm/test/CodeGen/SPIRV/transcoding/OpImageReadMS.ll
+++ b/llvm/test/CodeGen/SPIRV/transcoding/OpImageReadMS.ll
@@ -1,5 +1,6 @@
; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; CHECK-SPIRV: OpCapability StorageImageReadWithoutFormat
; CHECK-SPIRV: %[[#]] = OpImageRead %[[#]] %[[#]] %[[#]] Sample %[[#]]
define spir_kernel void @sample_test(target("spirv.Image", void, 1, 0, 0, 1, 0, 0, 0) %source, i32 %sampler, <4 x float> addrspace(1)* nocapture %results) {
>From cadd46b2e8798ca6b12222a0ad5d1f0a03c0a820 Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenperron at google.com>
Date: Fri, 8 Nov 2024 10:46:49 -0500
Subject: [PATCH 5/7] Fixes from code review.
---
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 3 +
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h | 2 +-
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 78 +++++++++----------
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 4 +-
4 files changed, 44 insertions(+), 43 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 694497f9e68675..829ff9606f635d 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -1143,6 +1143,9 @@ SPIRVGlobalRegistry::getScalarOrVectorComponentType(SPIRVType *Type) const {
Register ScalarReg = Type->getOpcode() == SPIRV::OpTypeVector
? Type->getOperand(1).getReg()
: Type->getOperand(0).getReg();
+ SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarReg);
+ assert(isScalarOrVectorOfType(Type->getOperand(0).getReg(),
+ ScalarType->getOpcode()));
return getSPIRVTypeForVReg(ScalarReg);
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index 0cf174d0e45afa..7dfe8ef6366f9b 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -392,7 +392,7 @@ class SPIRVGlobalRegistry {
unsigned getScalarOrVectorComponentCount(SPIRVType *Type) const;
// Return the component type in a vector if the argument is associated with
- // a vector type. Returns the argument itself for a scalar type, and nullptr
+ // a vector type. Returns the argument itself for other types, and nullptr
// for a missing type.
SPIRVType *getScalarOrVectorComponentType(Register VReg) const;
SPIRVType *getScalarOrVectorComponentType(SPIRVType *Type) const;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index c3b1122769813f..356faefb602990 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -32,6 +32,7 @@
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/IR/IntrinsicsSPIRV.h"
#include "llvm/Support/Debug.h"
+#include <llvm-14/llvm/ADT/StringExtras.h>
#define DEBUG_TYPE "spirv-isel"
@@ -291,12 +292,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
uint32_t Binding, uint32_t ArraySize,
Register IndexReg, bool IsNonUniform,
MachineIRBuilder MIRBuilder) const;
- SPIRVType *getCorrespondingVec4Type(const SPIRVType *Type,
- MachineInstr &I) const;
- void extractScalarOrVectorFromVector(Register &ResultReg,
- const SPIRVType *ResType,
- Register &InputReg,
- MachineInstr &InsertionPoint) const;
+ SPIRVType *widenTypeToVec4(const SPIRVType *Type, MachineInstr &I) const;
+ void extractSubvector(Register &ResVReg, const SPIRVType *ResType,
+ Register &ReadReg, MachineInstr &InsertionPoint) const;
};
} // end anonymous namespace
@@ -2826,8 +2824,20 @@ void SPIRVInstructionSelector::selectReadImageIntrinsic(
// We will do that when we can, but for now trying to move forward with other
// issues.
Register ImageReg = I.getOperand(2).getReg();
+ assert(MRI->getVRegDef(ImageReg)->getParent() == I.getParent() &&
+ "The image must be loaded in the same basic block as its use.");
- SPIRVType *ReadType = getCorrespondingVec4Type(ResType, I);
+ uint64_t ResultSize = GR.getScalarOrVectorComponentCount(ResType);
+ if (ResultSize == 4) {
+ BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpImageRead))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(ImageReg)
+ .addUse(I.getOperand(3).getReg());
+ return;
+ }
+
+ SPIRVType *ReadType = widenTypeToVec4(ResType, I);
Register ReadReg = MRI->createVirtualRegister(GR.getRegClass(ReadType));
BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpImageRead))
.addDef(ReadReg)
@@ -2835,57 +2845,46 @@ void SPIRVInstructionSelector::selectReadImageIntrinsic(
.addUse(ImageReg)
.addUse(I.getOperand(3).getReg());
- extractScalarOrVectorFromVector(ResVReg, ResType, ReadReg, I);
-}
-
-void SPIRVInstructionSelector::extractScalarOrVectorFromVector(
- Register &ResultReg, const SPIRVType *ResType, Register &InputReg,
- MachineInstr &InsertionPoint) const {
- SPIRVType *InputType = GR.getResultType(InputReg);
- assert(InputType->getOpcode() == SPIRV::OpTypeVector);
-
- if (ResType->getOpcode() != SPIRV::OpTypeVector) {
- assert(ResType == GR.getScalarOrVectorComponentType(InputType));
- BuildMI(*InsertionPoint.getParent(), InsertionPoint,
- InsertionPoint.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
- .addDef(ResultReg)
+ if (ResultSize == 1) {
+ BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(SPIRV::OpCompositeExtract))
+ .addDef(ResVReg)
.addUse(GR.getSPIRVTypeID(ResType))
- .addUse(InputReg)
+ .addUse(ReadReg)
.addImm(0);
return;
}
+ extractSubvector(ResVReg, ResType, ReadReg, I);
+}
+void SPIRVInstructionSelector::extractSubvector(
+ Register &ResVReg, const SPIRVType *ResType, Register &ReadReg,
+ MachineInstr &InsertionPoint) const {
+ SPIRVType *InputType = GR.getResultType(ReadReg);
uint64_t InputSize = GR.getScalarOrVectorComponentCount(InputType);
- uint64_t VectorSize = GR.getScalarOrVectorComponentCount(ResType);
- if (VectorSize == InputSize) {
- BuildMI(*InsertionPoint.getParent(), InsertionPoint,
- InsertionPoint.getDebugLoc(), TII.get(SPIRV::OpCopyObject))
- .addDef(ResultReg)
- .addUse(GR.getSPIRVTypeID(ResType))
- .addUse(InputReg);
- return;
- }
-
- assert(VectorSize < InputSize &&
+ uint64_t ResultSize = GR.getScalarOrVectorComponentCount(ResType);
+ assert(InputSize > 1 && "The input must be a vector.");
+ assert(ResultSize > 1 && "The result must be a vector.");
+ assert(ResultSize < InputSize &&
"Cannot extract more element than there are in the input.");
SmallVector<Register> ComponentRegisters;
SPIRVType *ScalarType = GR.getScalarOrVectorComponentType(ResType);
const TargetRegisterClass *ScalarRegClass = GR.getRegClass(ScalarType);
- for (uint64_t i = 0; i < VectorSize; i++) {
+ for (uint64_t I = 0; I < ResultSize; I++) {
Register ComponentReg = MRI->createVirtualRegister(ScalarRegClass);
BuildMI(*InsertionPoint.getParent(), InsertionPoint,
InsertionPoint.getDebugLoc(), TII.get(SPIRV::OpCompositeExtract))
.addDef(ComponentReg)
.addUse(ScalarType->getOperand(0).getReg())
- .addUse(InputReg)
- .addImm(i);
+ .addUse(ReadReg)
+ .addImm(I);
ComponentRegisters.emplace_back(ComponentReg);
}
MachineInstrBuilder MIB = BuildMI(*InsertionPoint.getParent(), InsertionPoint,
InsertionPoint.getDebugLoc(),
TII.get(SPIRV::OpCompositeConstruct))
- .addDef(ResultReg)
+ .addDef(ResVReg)
.addUse(GR.getSPIRVTypeID(ResType));
for (Register ComponentReg : ComponentRegisters) {
@@ -3395,9 +3394,8 @@ bool SPIRVInstructionSelector::selectSpvThreadId(Register ResVReg,
return MIB.constrainAllUses(TII, TRI, RBI);
}
-SPIRVType *
-SPIRVInstructionSelector::getCorrespondingVec4Type(const SPIRVType *Type,
- MachineInstr &I) const {
+SPIRVType *SPIRVInstructionSelector::widenTypeToVec4(const SPIRVType *Type,
+ MachineInstr &I) const {
MachineIRBuilder MIRBuilder(I);
if (Type->getOpcode() != SPIRV::OpTypeVector) {
return GR.getOrCreateSPIRVVectorType(Type, 4, MIRBuilder);
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 6cddddd95ffc24..1995ff12057dc1 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -1011,7 +1011,7 @@ void addOpAccessChainReqs(const MachineInstr &Instr,
}
}
-static bool imageTypeHasUnknownFormat(SPIRVType *TypeInst) {
+static bool isImageTypeWithUnknownFormat(SPIRVType *TypeInst) {
if (TypeInst->getOpcode() != SPIRV::OpTypeImage)
return false;
assert(TypeInst->getOperand(7).isImm() && "The image format must be an imm.");
@@ -1427,7 +1427,7 @@ void addInstrRequirements(const MachineInstr &MI,
case SPIRV::OpImageRead: {
Register ImageReg = MI.getOperand(2).getReg();
SPIRVType *TypeDef = ST.getSPIRVGlobalRegistry()->getResultType(ImageReg);
- if (imageTypeHasUnknownFormat(TypeDef))
+ if (isImageTypeWithUnknownFormat(TypeDef))
Reqs.addCapability(SPIRV::Capability::StorageImageReadWithoutFormat);
break;
}
>From 3b1e05a4d28d561eeabfdcf147a96bd4ce2593c9 Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenperron at google.com>
Date: Fri, 8 Nov 2024 12:46:33 -0500
Subject: [PATCH 6/7] More fixes.
---
llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 11 ++++-------
llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp | 3 +--
2 files changed, 5 insertions(+), 9 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 356faefb602990..2a916e3db1146e 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -22,6 +22,7 @@
#include "SPIRVTargetMachine.h"
#include "SPIRVUtils.h"
#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
@@ -32,7 +33,6 @@
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/IR/IntrinsicsSPIRV.h"
#include "llvm/Support/Debug.h"
-#include <llvm-14/llvm/ADT/StringExtras.h>
#define DEBUG_TYPE "spirv-isel"
@@ -2887,9 +2887,8 @@ void SPIRVInstructionSelector::extractSubvector(
.addDef(ResVReg)
.addUse(GR.getSPIRVTypeID(ResType));
- for (Register ComponentReg : ComponentRegisters) {
+ for (Register ComponentReg : ComponentRegisters)
MIB.addUse(ComponentReg);
- }
}
Register SPIRVInstructionSelector::buildPointerToResource(
@@ -3397,14 +3396,12 @@ bool SPIRVInstructionSelector::selectSpvThreadId(Register ResVReg,
SPIRVType *SPIRVInstructionSelector::widenTypeToVec4(const SPIRVType *Type,
MachineInstr &I) const {
MachineIRBuilder MIRBuilder(I);
- if (Type->getOpcode() != SPIRV::OpTypeVector) {
+ if (Type->getOpcode() != SPIRV::OpTypeVector)
return GR.getOrCreateSPIRVVectorType(Type, 4, MIRBuilder);
- }
uint64_t VectorSize = Type->getOperand(2).getImm();
- if (VectorSize == 4) {
+ if (VectorSize == 4)
return Type;
- }
Register ScalarTypeReg = Type->getOperand(1).getReg();
const SPIRVType *ScalarType = GR.getSPIRVTypeForVReg(ScalarTypeReg);
diff --git a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
index 1995ff12057dc1..0308c56093064c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVModuleAnalysis.cpp
@@ -722,9 +722,8 @@ void RequirementHandler::initAvailableCapabilitiesForVulkan(
}
// Became core in Vulkan 1.3
- if (ST.isAtLeastSPIRVVer(VersionTuple(1, 6))) {
+ if (ST.isAtLeastSPIRVVer(VersionTuple(1, 6)))
addAvailableCaps({Capability::StorageImageReadWithoutFormat});
- }
}
} // namespace SPIRV
>From 584373cd7091ec09cddaab54933957749bc11511 Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenperron at google.com>
Date: Tue, 12 Nov 2024 10:13:51 -0500
Subject: [PATCH 7/7] Fixes
---
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 829ff9606f635d..6f222883ee07de 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -1057,7 +1057,7 @@ SPIRVGlobalRegistry::getSPIRVTypeForVReg(Register VReg,
}
SPIRVType *SPIRVGlobalRegistry::getResultType(Register VReg) {
- MachineInstr *Instr = CurMF->getRegInfo().getVRegDef(VReg);
+ MachineInstr *Instr = getVRegDef(CurMF->getRegInfo(), VReg);
return getSPIRVTypeForVReg(Instr->getOperand(1).getReg());
}
@@ -1146,7 +1146,7 @@ SPIRVGlobalRegistry::getScalarOrVectorComponentType(SPIRVType *Type) const {
SPIRVType *ScalarType = getSPIRVTypeForVReg(ScalarReg);
assert(isScalarOrVectorOfType(Type->getOperand(0).getReg(),
ScalarType->getOpcode()));
- return getSPIRVTypeForVReg(ScalarReg);
+ return ScalarType;
}
unsigned
More information about the llvm-commits
mailing list