[llvm-branch-commits] [llvm] [SPIRV] Add get dimension intrinsics. (PR #189746)
Steven Perron via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Apr 1 07:11:38 PDT 2026
https://github.com/s-perron updated https://github.com/llvm/llvm-project/pull/189746
>From 439b45fdf29e3b2c79651c78ae874ff63bf2391e Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenperron at google.com>
Date: Mon, 30 Mar 2026 13:26:43 -0400
Subject: [PATCH 1/2] [SPIRV] Add get dimension intrinsics.
Add the intrinsics in the wg-hlsl proposal
[[0033] - GetDimensions mapping to built-ins functions and LLVM intrinsics](https://github.com/llvm/wg-hlsl/blob/main/proposals/0033-resources-get-dimensions.md#lowering-to-spir-v)
to the SPIR-V backend. This enabled us to implement the GetDimensions methods
in textures in Clang.
Assisted-by: Gemini
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 16 +-
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 221 ++++++++++++++++++
.../SPIRV/hlsl-resources/GetDimensions.ll | 106 +++++++++
.../hlsl-resources/GetDimensionsFloat.ll | 25 ++
4 files changed, 367 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensions.ll
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensionsFloat.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index f7dd81f3c57c3..a252e0bafe2be 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -204,7 +204,21 @@ def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]
[IntrInaccessibleMemOrArgMemOnly]>;
def int_spv_resource_getdimensions_x
- : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>;
+ : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty], [IntrReadMem]>;
+ def int_spv_resource_getdimensions_xy
+ : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty], [IntrReadMem]>;
+ def int_spv_resource_getdimensions_xyz
+ : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty], [IntrReadMem]>;
+ def int_spv_resource_getdimensions_levels_x
+ : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty, llvm_i32_ty], [IntrReadMem]>;
+ def int_spv_resource_getdimensions_levels_xy
+ : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty, llvm_i32_ty], [IntrReadMem]>;
+ def int_spv_resource_getdimensions_levels_xyz
+ : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty, llvm_i32_ty], [IntrReadMem]>;
+ def int_spv_resource_getdimensions_ms_xy
+ : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty], [IntrReadMem]>;
+ def int_spv_resource_getdimensions_ms_xyz
+ : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty], [IntrReadMem]>;
def int_spv_resource_sample
: DefaultAttrsIntrinsic<
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 5068497f20ea9..6a847073c6202 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -34,6 +34,7 @@
#include "llvm/IR/IntrinsicsSPIRV.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
+#include <optional>
#define DEBUG_TYPE "spirv-isel"
@@ -381,6 +382,16 @@ class SPIRVInstructionSelector : public InstructionSelector {
bool selectReadImageIntrinsic(Register &ResVReg, SPIRVTypeInst ResType,
MachineInstr &I) const;
+ bool selectGetDimensionsIntrinsic(Register &ResVReg, SPIRVTypeInst ResType,
+ MachineInstr &I) const;
+ bool selectGetDimensionsLevelsIntrinsic(Register &ResVReg,
+ SPIRVTypeInst ResType,
+ MachineInstr &I) const;
+ bool selectGetDimensionsMSIntrinsic(Register &ResVReg, SPIRVTypeInst ResType,
+ MachineInstr &I) const;
+ bool
+ selectImageQuerySize(Register ImageReg, Register &ResVReg, MachineInstr &I,
+ std::optional<Register> LodReg = std::nullopt) const;
bool selectSampleBasicIntrinsic(Register &ResVReg, SPIRVTypeInst ResType,
MachineInstr &I) const;
bool selectCalculateLodIntrinsic(Register &ResVReg, SPIRVTypeInst ResType,
@@ -4634,6 +4645,20 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
case Intrinsic::spv_resource_load_level: {
return selectLoadLevelIntrinsic(ResVReg, ResType, I);
}
+ case Intrinsic::spv_resource_getdimensions_x:
+ case Intrinsic::spv_resource_getdimensions_xy:
+ case Intrinsic::spv_resource_getdimensions_xyz: {
+ return selectGetDimensionsIntrinsic(ResVReg, ResType, I);
+ }
+ case Intrinsic::spv_resource_getdimensions_levels_x:
+ case Intrinsic::spv_resource_getdimensions_levels_xy:
+ case Intrinsic::spv_resource_getdimensions_levels_xyz: {
+ return selectGetDimensionsLevelsIntrinsic(ResVReg, ResType, I);
+ }
+ case Intrinsic::spv_resource_getdimensions_ms_xy:
+ case Intrinsic::spv_resource_getdimensions_ms_xyz: {
+ return selectGetDimensionsMSIntrinsic(ResVReg, ResType, I);
+ }
case Intrinsic::spv_resource_calculate_lod:
case Intrinsic::spv_resource_calculate_lod_unclamped:
return selectCalculateLodIntrinsic(ResVReg, ResType, I);
@@ -4948,6 +4973,202 @@ bool SPIRVInstructionSelector::generateSampleImage(
return true;
}
+bool SPIRVInstructionSelector::selectImageQuerySize(
+ Register ImageReg, Register &ResVReg, MachineInstr &I,
+ std::optional<Register> LodReg) const {
+ unsigned Opcode =
+ LodReg ? SPIRV::OpImageQuerySizeLod : SPIRV::OpImageQuerySize;
+ SPIRVTypeInst ImageType = GR.getSPIRVTypeForVReg(ImageReg);
+ assert(ImageType && ImageType->getOpcode() == SPIRV::OpTypeImage &&
+ "ImageReg is not an image type.");
+
+ auto Dim = static_cast<SPIRV::Dim::Dim>(ImageType->getOperand(2).getImm());
+ bool IsArray = ImageType->getOperand(4).getImm() != 0;
+ unsigned NumComponents = 0;
+ switch (Dim) {
+ case SPIRV::Dim::DIM_1D:
+ case SPIRV::Dim::DIM_Buffer:
+ NumComponents = IsArray ? 2 : 1;
+ break;
+ case SPIRV::Dim::DIM_2D:
+ case SPIRV::Dim::DIM_Cube:
+ case SPIRV::Dim::DIM_Rect:
+ NumComponents = IsArray ? 3 : 2;
+ break;
+ case SPIRV::Dim::DIM_3D:
+ NumComponents = 3;
+ break;
+ default:
+ I.emitGenericError("Unsupported image dimension for OpImageQuerySize.");
+ return false;
+ }
+
+ SPIRVTypeInst I32Ty = GR.getOrCreateSPIRVIntegerType(32, I, TII);
+ SPIRVTypeInst ResType =
+ NumComponents == 1
+ ? I32Ty
+ : GR.getOrCreateSPIRVVectorType(I32Ty, NumComponents, I, TII);
+
+ auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(ImageReg);
+ if (LodReg)
+ MIB.addUse(*LodReg);
+ MIB.constrainAllUses(TII, TRI, RBI);
+ return true;
+}
+
+bool SPIRVInstructionSelector::selectGetDimensionsIntrinsic(
+ Register &ResVReg, SPIRVTypeInst ResType, MachineInstr &I) const {
+ Register ImageReg = I.getOperand(2).getReg();
+ auto *ImageDef = cast<GIntrinsic>(getVRegDef(*MRI, ImageReg));
+ Register NewImageReg = MRI->createVirtualRegister(MRI->getRegClass(ImageReg));
+ if (!loadHandleBeforePosition(NewImageReg, GR.getSPIRVTypeForVReg(ImageReg),
+ *ImageDef, I)) {
+ return false;
+ }
+ SPIRVTypeInst ScalarResTy = GR.getScalarOrVectorComponentType(ResType);
+ bool IsFloat = ScalarResTy->getOpcode() == SPIRV::OpTypeFloat;
+
+ Register QueryResultReg =
+ IsFloat ? MRI->createVirtualRegister(&SPIRV::iIDRegClass) : ResVReg;
+
+ if (!selectImageQuerySize(NewImageReg, QueryResultReg, I, std::nullopt))
+ return false;
+
+ if (IsFloat) {
+ BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpConvertUToF))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(QueryResultReg)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ return true;
+}
+
+bool SPIRVInstructionSelector::selectGetDimensionsLevelsIntrinsic(
+ Register &ResVReg, SPIRVTypeInst ResType, MachineInstr &I) const {
+ Register ImageReg = I.getOperand(2).getReg();
+ auto *ImageDef = cast<GIntrinsic>(getVRegDef(*MRI, ImageReg));
+ Register NewImageReg = MRI->createVirtualRegister(MRI->getRegClass(ImageReg));
+ if (!loadHandleBeforePosition(NewImageReg, GR.getSPIRVTypeForVReg(ImageReg),
+ *ImageDef, I)) {
+ return false;
+ }
+
+ SPIRVTypeInst ScalarResTy = GR.getScalarOrVectorComponentType(ResType);
+ bool IsFloat = ScalarResTy->getOpcode() == SPIRV::OpTypeFloat;
+
+ Register SizeReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
+ Register LodReg = I.getOperand(3).getReg();
+
+ assert(GR.getSPIRVTypeForVReg(NewImageReg)->getOperand(6).getImm() == 1 &&
+ "OpImageQuerySizeLod and OpImageQueryLevels require a sampled image");
+
+ if (!selectImageQuerySize(NewImageReg, SizeReg, I, LodReg)) {
+ return false;
+ }
+
+ SPIRVTypeInst I32Ty = GR.getOrCreateSPIRVIntegerType(32, I, TII);
+ Register LevelsReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
+ BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(SPIRV::OpImageQueryLevels))
+ .addDef(LevelsReg)
+ .addUse(GR.getSPIRVTypeID(I32Ty))
+ .addUse(NewImageReg)
+ .constrainAllUses(TII, TRI, RBI);
+
+ SPIRVTypeInst IntResTy = ResType;
+ Register CompositeReg = ResVReg;
+ if (IsFloat) {
+ unsigned NumResComponents = GR.getScalarOrVectorComponentCount(ResType);
+ IntResTy =
+ NumResComponents == 1
+ ? I32Ty
+ : GR.getOrCreateSPIRVVectorType(I32Ty, NumResComponents, I, TII);
+ CompositeReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
+ }
+
+ BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(SPIRV::OpCompositeConstruct))
+ .addDef(CompositeReg)
+ .addUse(GR.getSPIRVTypeID(IntResTy))
+ .addUse(SizeReg)
+ .addUse(LevelsReg)
+ .constrainAllUses(TII, TRI, RBI);
+
+ if (IsFloat) {
+ BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpConvertUToF))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(CompositeReg)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ return true;
+}
+
+bool SPIRVInstructionSelector::selectGetDimensionsMSIntrinsic(
+ Register &ResVReg, SPIRVTypeInst ResType, MachineInstr &I) const {
+ Register ImageReg = I.getOperand(2).getReg();
+ auto *ImageDef = cast<GIntrinsic>(getVRegDef(*MRI, ImageReg));
+ Register NewImageReg = MRI->createVirtualRegister(MRI->getRegClass(ImageReg));
+ if (!loadHandleBeforePosition(NewImageReg, GR.getSPIRVTypeForVReg(ImageReg),
+ *ImageDef, I)) {
+ return false;
+ }
+
+ SPIRVTypeInst ScalarResTy = GR.getScalarOrVectorComponentType(ResType);
+ bool IsFloat = ScalarResTy->getOpcode() == SPIRV::OpTypeFloat;
+
+ Register SizeReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
+
+ assert(GR.getSPIRVTypeForVReg(NewImageReg)->getOperand(5).getImm() == 1 &&
+ "OpImageQuerySamples requires a multisampled image");
+
+ if (!selectImageQuerySize(NewImageReg, SizeReg, I, std::nullopt)) {
+ return false;
+ }
+
+ Register SamplesReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
+
+ SPIRVTypeInst I32Ty = GR.getOrCreateSPIRVIntegerType(32, I, TII);
+ BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(SPIRV::OpImageQuerySamples))
+ .addDef(SamplesReg)
+ .addUse(GR.getSPIRVTypeID(I32Ty))
+ .addUse(NewImageReg)
+ .constrainAllUses(TII, TRI, RBI);
+
+ SPIRVTypeInst IntResTy = ResType;
+ Register CompositeReg = ResVReg;
+ if (IsFloat) {
+ unsigned NumResComponents = GR.getScalarOrVectorComponentCount(ResType);
+ IntResTy =
+ NumResComponents == 1
+ ? I32Ty
+ : GR.getOrCreateSPIRVVectorType(I32Ty, NumResComponents, I, TII);
+ CompositeReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
+ }
+
+ BuildMI(*I.getParent(), I, I.getDebugLoc(),
+ TII.get(SPIRV::OpCompositeConstruct))
+ .addDef(CompositeReg)
+ .addUse(GR.getSPIRVTypeID(IntResTy))
+ .addUse(SizeReg)
+ .addUse(SamplesReg)
+ .constrainAllUses(TII, TRI, RBI);
+
+ if (IsFloat) {
+ BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpConvertUToF))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addUse(CompositeReg)
+ .constrainAllUses(TII, TRI, RBI);
+ }
+ return true;
+}
+
bool SPIRVInstructionSelector::selectCalculateLodIntrinsic(
Register &ResVReg, SPIRVTypeInst ResType, MachineInstr &I) const {
Register ImageReg = I.getOperand(2).getReg();
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensions.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensions.ll
new file mode 100644
index 0000000000000..deca5c9beb2cf
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensions.ll
@@ -0,0 +1,106 @@
+; RUN: llc -O0 -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 --target-env vulkan1.3 %}
+
+; CHECK-DAG: %[[int:[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: %[[v2int:[0-9]+]] = OpTypeVector %[[int]] 2
+; CHECK-DAG: %[[v3int:[0-9]+]] = OpTypeVector %[[int]] 3
+; CHECK-DAG: %[[v4int:[0-9]+]] = OpTypeVector %[[int]] 4
+; CHECK-DAG: %[[float:[0-9]+]] = OpTypeFloat 32
+; CHECK-DAG: %[[image1d_s1:[0-9]+]] = OpTypeImage %[[float]] 1D 2 0 0 1 Unknown
+; CHECK-DAG: %[[image2d_s1:[0-9]+]] = OpTypeImage %[[float]] 2D 2 0 0 1 Unknown
+; CHECK-DAG: %[[image3d_s1:[0-9]+]] = OpTypeImage %[[float]] 3D 2 0 0 1 Unknown
+; CHECK-DAG: %[[image1d_s2:[0-9]+]] = OpTypeImage %[[float]] 1D 2 0 0 2 Unknown
+; CHECK-DAG: %[[image2d_s2:[0-9]+]] = OpTypeImage %[[float]] 2D 2 0 0 2 Unknown
+; CHECK-DAG: %[[image3d_s2:[0-9]+]] = OpTypeImage %[[float]] 3D 2 0 0 2 Unknown
+; CHECK-DAG: %[[imagems:[0-9]+]] = OpTypeImage %[[float]] 2D 2 0 1 1 Unknown
+; CHECK-DAG: %[[imagemsarray:[0-9]+]] = OpTypeImage %[[float]] 2D 2 1 1 1 Unknown
+; CHECK-DAG: %[[int_0:[0-9]+]] = OpConstant %[[int]] 0
+
+ at .str1 = private unnamed_addr constant [6 x i8] c"img1d\00", align 1
+ at .str2 = private unnamed_addr constant [6 x i8] c"img2d\00", align 1
+ at .str3 = private unnamed_addr constant [6 x i8] c"img3d\00", align 1
+ at .str4 = private unnamed_addr constant [9 x i8] c"img1dlod\00", align 1
+ at .str5 = private unnamed_addr constant [9 x i8] c"img2dlod\00", align 1
+ at .str6 = private unnamed_addr constant [9 x i8] c"img3dlod\00", align 1
+ at .str7 = private unnamed_addr constant [6 x i8] c"imgms\00", align 1
+ at .str8 = private unnamed_addr constant [11 x i8] c"imgmsarray\00", align 1
+
+define void @main() #0 {
+entry:
+ %img1d = tail call target("spirv.Image", float, 0, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_0_2_0_0_2_0t(i32 0, i32 0, i32 1, i32 0, ptr @.str1)
+ %img2d = tail call target("spirv.Image", float, 1, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_0_0_2_0t(i32 0, i32 1, i32 1, i32 0, ptr @.str2)
+ %img3d = tail call target("spirv.Image", float, 2, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_2_2_0_0_2_0t(i32 0, i32 2, i32 1, i32 0, ptr @.str3)
+
+ %img1dlod = tail call target("spirv.Image", float, 0, 2, 0, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_0_2_0_0_1_0t(i32 0, i32 3, i32 1, i32 0, ptr @.str4)
+ %img2dlod = tail call target("spirv.Image", float, 1, 2, 0, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_0_0_1_0t(i32 0, i32 4, i32 1, i32 0, ptr @.str5)
+ %img3dlod = tail call target("spirv.Image", float, 2, 2, 0, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_2_2_0_0_1_0t(i32 0, i32 5, i32 1, i32 0, ptr @.str6)
+
+ %imgms = tail call target("spirv.Image", float, 1, 2, 0, 1, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_0_1_1_0t(i32 0, i32 6, i32 1, i32 0, ptr @.str7)
+ %imgmsarray = tail call target("spirv.Image", float, 1, 2, 1, 1, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_1_1_0t(i32 0, i32 7, i32 1, i32 0, ptr @.str8)
+
+; CHECK: %[[img1d_val:[0-9]+]] = OpLoad %[[image1d_s2]]
+; CHECK: OpImageQuerySize %[[int]] %[[img1d_val]]
+ %res0 = call i32 @llvm.spv.resource.getdimensions.x.i32.tspirv.Image_f32_0_2_0_0_2_0t(target("spirv.Image", float, 0, 2, 0, 0, 2, 0) %img1d)
+
+; CHECK: %[[img2d_val:[0-9]+]] = OpLoad %[[image2d_s2]]
+; CHECK: OpImageQuerySize %[[v2int]] %[[img2d_val]]
+ %res1 = call <2 x i32> @llvm.spv.resource.getdimensions.xy.v2i32.tspirv.Image_f32_1_2_0_0_2_0t(target("spirv.Image", float, 1, 2, 0, 0, 2, 0) %img2d)
+
+; CHECK: %[[img3d_val:[0-9]+]] = OpLoad %[[image3d_s2]]
+; CHECK: OpImageQuerySize %[[v3int]] %[[img3d_val]]
+ %res2 = call <3 x i32> @llvm.spv.resource.getdimensions.xyz.v3i32.tspirv.Image_f32_2_2_0_0_2_0t(target("spirv.Image", float, 2, 2, 0, 0, 2, 0) %img3d)
+
+; CHECK: %[[img1dlod_val:[0-9]+]] = OpLoad %[[image1d_s1]]
+; CHECK: %[[size3:[0-9]+]] = OpImageQuerySizeLod %[[int]] %[[img1dlod_val]] %[[int_0]]
+; CHECK: %[[levels3:[0-9]+]] = OpImageQueryLevels %[[int]] %[[img1dlod_val]]
+; CHECK: OpCompositeConstruct %[[v2int]] %[[size3]] %[[levels3]]
+ %res3 = call <2 x i32> @llvm.spv.resource.getdimensions.levels.x.v2i32.tspirv.Image_f32_0_2_0_0_1_0t(target("spirv.Image", float, 0, 2, 0, 0, 1, 0) %img1dlod, i32 0)
+
+; CHECK: %[[img2dlod_val:[0-9]+]] = OpLoad %[[image2d_s1]]
+; CHECK: %[[size4:[0-9]+]] = OpImageQuerySizeLod %[[v2int]] %[[img2dlod_val]] %[[int_0]]
+; CHECK: %[[levels4:[0-9]+]] = OpImageQueryLevels %[[int]] %[[img2dlod_val]]
+; CHECK: OpCompositeConstruct %[[v3int]] %[[size4]] %[[levels4]]
+ %res4 = call <3 x i32> @llvm.spv.resource.getdimensions.levels.xy.v3i32.tspirv.Image_f32_1_2_0_0_1_0t(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %img2dlod, i32 0)
+
+; CHECK: %[[img3dlod_val:[0-9]+]] = OpLoad %[[image3d_s1]]
+; CHECK: %[[size5:[0-9]+]] = OpImageQuerySizeLod %[[v3int]] %[[img3dlod_val]] %[[int_0]]
+; CHECK: %[[levels5:[0-9]+]] = OpImageQueryLevels %[[int]] %[[img3dlod_val]]
+; CHECK: OpCompositeConstruct %[[v4int]] %[[size5]] %[[levels5]]
+ %res5 = call <4 x i32> @llvm.spv.resource.getdimensions.levels.xyz.v4i32.tspirv.Image_f32_2_2_0_0_1_0t(target("spirv.Image", float, 2, 2, 0, 0, 1, 0) %img3dlod, i32 0)
+
+; CHECK: %[[imgms_val:[0-9]+]] = OpLoad %[[imagems]]
+; CHECK: %[[size6:[0-9]+]] = OpImageQuerySize %[[v2int]] %[[imgms_val]]
+; CHECK: %[[samp6:[0-9]+]] = OpImageQuerySamples %[[int]] %[[imgms_val]]
+; CHECK: OpCompositeConstruct %[[v3int]] %[[size6]] %[[samp6]]
+ %res6 = call <3 x i32> @llvm.spv.resource.getdimensions.ms.xy.v3i32.tspirv.Image_f32_1_2_0_1_1_0t(target("spirv.Image", float, 1, 2, 0, 1, 1, 0) %imgms)
+
+; CHECK: %[[imgmsarray_val:[0-9]+]] = OpLoad %[[imagemsarray]]
+; CHECK: %[[size7:[0-9]+]] = OpImageQuerySize %[[v3int]] %[[imgmsarray_val]]
+; CHECK: %[[samp7:[0-9]+]] = OpImageQuerySamples %[[int]] %[[imgmsarray_val]]
+; CHECK: OpCompositeConstruct %[[v4int]] %[[size7]] %[[samp7]]
+ %res7 = call <4 x i32> @llvm.spv.resource.getdimensions.ms.xyz.v4i32.tspirv.Image_f32_1_2_1_1_1_0t(target("spirv.Image", float, 1, 2, 1, 1, 1, 0) %imgmsarray)
+
+ ret void
+}
+
+attributes #0 = { "hlsl.shader"="pixel" }
+
+declare target("spirv.Image", float, 0, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_0_2_0_0_2_0t(i32, i32, i32, i32, ptr)
+declare target("spirv.Image", float, 1, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_0_0_2_0t(i32, i32, i32, i32, ptr)
+declare target("spirv.Image", float, 2, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_2_2_0_0_2_0t(i32, i32, i32, i32, ptr)
+declare target("spirv.Image", float, 0, 2, 0, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_0_2_0_0_1_0t(i32, i32, i32, i32, ptr)
+declare target("spirv.Image", float, 1, 2, 0, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_0_0_1_0t(i32, i32, i32, i32, ptr)
+declare target("spirv.Image", float, 2, 2, 0, 0, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_2_2_0_0_1_0t(i32, i32, i32, i32, ptr)
+declare target("spirv.Image", float, 1, 2, 0, 1, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_0_1_1_0t(i32, i32, i32, i32, ptr)
+declare target("spirv.Image", float, 1, 2, 1, 1, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_1_1_0t(i32, i32, i32, i32, ptr)
+
+declare i32 @llvm.spv.resource.getdimensions.x.i32.tspirv.Image_f32_0_2_0_0_2_0t(target("spirv.Image", float, 0, 2, 0, 0, 2, 0))
+declare <2 x i32> @llvm.spv.resource.getdimensions.xy.v2i32.tspirv.Image_f32_1_2_0_0_2_0t(target("spirv.Image", float, 1, 2, 0, 0, 2, 0))
+declare <3 x i32> @llvm.spv.resource.getdimensions.xyz.v3i32.tspirv.Image_f32_2_2_0_0_2_0t(target("spirv.Image", float, 2, 2, 0, 0, 2, 0))
+
+declare <2 x i32> @llvm.spv.resource.getdimensions.levels.x.v2i32.tspirv.Image_f32_0_2_0_0_1_0t(target("spirv.Image", float, 0, 2, 0, 0, 1, 0), i32)
+declare <3 x i32> @llvm.spv.resource.getdimensions.levels.xy.v3i32.tspirv.Image_f32_1_2_0_0_1_0t(target("spirv.Image", float, 1, 2, 0, 0, 1, 0), i32)
+declare <4 x i32> @llvm.spv.resource.getdimensions.levels.xyz.v4i32.tspirv.Image_f32_2_2_0_0_1_0t(target("spirv.Image", float, 2, 2, 0, 0, 1, 0), i32)
+
+declare <3 x i32> @llvm.spv.resource.getdimensions.ms.xy.v3i32.tspirv.Image_f32_1_2_0_1_1_0t(target("spirv.Image", float, 1, 2, 0, 1, 1, 0))
+declare <4 x i32> @llvm.spv.resource.getdimensions.ms.xyz.v4i32.tspirv.Image_f32_1_2_1_1_1_0t(target("spirv.Image", float, 1, 2, 1, 1, 1, 0))
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensionsFloat.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensionsFloat.ll
new file mode 100644
index 0000000000000..7998d2c7814a0
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensionsFloat.ll
@@ -0,0 +1,25 @@
+; RUN: llc -O0 -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 --target-env vulkan1.3 %}
+
+; CHECK-DAG: [[FLOAT_TY:%[0-9]+]] = OpTypeFloat 32
+; CHECK-DAG: [[IMG_TY:%[0-9]+]] = OpTypeImage [[FLOAT_TY]] 1D 2 0 0 2 Unknown
+; CHECK-DAG: [[INT_TY:%[0-9]+]] = OpTypeInt 32 0
+; CHECK-DAG: [[PTR_IMG_TY:%[0-9]+]] = OpTypePointer UniformConstant [[IMG_TY]]
+; CHECK: [[VAR:%[0-9]+]] = OpVariable [[PTR_IMG_TY]] UniformConstant
+; CHECK: [[LOAD:%[0-9]+]] = OpLoad [[IMG_TY]] [[VAR]]
+; CHECK: [[QUERY:%[0-9]+]] = OpImageQuerySize [[INT_TY]] [[LOAD]]
+; CHECK: {{%[0-9]+}} = OpConvertUToF [[FLOAT_TY]] [[QUERY]]
+
+ at .str1 = private unnamed_addr constant [6 x i8] c"img1d\00", align 1
+
+define void @main() #0 {
+entry:
+ %img1d = tail call target("spirv.Image", float, 0, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_0_2_0_0_2_0t(i32 0, i32 0, i32 1, i32 0, ptr @.str1)
+ %res0 = call float @llvm.spv.resource.getdimensions.x.f32.tspirv.Image_f32_0_2_0_0_2_0t(target("spirv.Image", float, 0, 2, 0, 0, 2, 0) %img1d)
+ ret void
+}
+
+attributes #0 = { "hlsl.shader"="pixel" }
+
+declare target("spirv.Image", float, 0, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_0_2_0_0_2_0t(i32, i32, i32, i32, ptr)
+declare float @llvm.spv.resource.getdimensions.x.f32.tspirv.Image_f32_0_2_0_0_2_0t(target("spirv.Image", float, 0, 2, 0, 0, 2, 0))
>From f2b29c3371324eaaa86317413bf33ba746fe9cea Mon Sep 17 00:00:00 2001
From: Steven Perron <stevenperron at google.com>
Date: Wed, 1 Apr 2026 10:04:34 -0400
Subject: [PATCH 2/2] [SPIRV] Enforce integer return types for GetDimensions
intrinsics
Update the `GetDimensions` intrinsics in the SPIR-V backend to strictly
return integer types (i32 or vectors of i32), aligning with the HLSL
design document for GetDimensions lowering. The intrinsics are no longer
overloaded on the return type.
As a result, instruction selection in `SPIRVInstructionSelector.cpp`
has been simplified by removing the logic that handles floating-point
returns and generates `OpConvertUToF` instructions. Floating-point
conversions are now expected to be handled by Clang codegen.
Updates:
- IntrinsicsSPIRV.td: Replaced `llvm_any_ty` with explicit integer
and integer vector types (`llvm_i32_ty`, `llvm_v2i32_ty`, etc.).
- SPIRVInstructionSelector.cpp: Removed floating-point type checks and
`OpConvertUToF` handling for GetDimensions.
- GetDimensions.ll: Updated to use the correct integer-only intrinsic
names without return type suffixes.
- GetDimensionsFloat.ll: Deleted, as the intrinsics no longer accept
floating-point return types directly.
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 16 ++---
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 70 ++-----------------
.../SPIRV/hlsl-resources/GetDimensions.ll | 32 ++++-----
.../hlsl-resources/GetDimensionsFloat.ll | 25 -------
4 files changed, 30 insertions(+), 113 deletions(-)
delete mode 100644 llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensionsFloat.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index a252e0bafe2be..d2a5fa1f08724 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -204,21 +204,21 @@ def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]
[IntrInaccessibleMemOrArgMemOnly]>;
def int_spv_resource_getdimensions_x
- : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty], [IntrReadMem]>;
+ : DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_any_ty], [IntrReadMem]>;
def int_spv_resource_getdimensions_xy
- : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty], [IntrReadMem]>;
+ : DefaultAttrsIntrinsic<[llvm_v2i32_ty], [llvm_any_ty], [IntrReadMem]>;
def int_spv_resource_getdimensions_xyz
- : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty], [IntrReadMem]>;
+ : DefaultAttrsIntrinsic<[llvm_v3i32_ty], [llvm_any_ty], [IntrReadMem]>;
def int_spv_resource_getdimensions_levels_x
- : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty, llvm_i32_ty], [IntrReadMem]>;
+ : DefaultAttrsIntrinsic<[llvm_v2i32_ty], [llvm_any_ty, llvm_i32_ty], [IntrReadMem]>;
def int_spv_resource_getdimensions_levels_xy
- : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty, llvm_i32_ty], [IntrReadMem]>;
+ : DefaultAttrsIntrinsic<[llvm_v3i32_ty], [llvm_any_ty, llvm_i32_ty], [IntrReadMem]>;
def int_spv_resource_getdimensions_levels_xyz
- : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty, llvm_i32_ty], [IntrReadMem]>;
+ : DefaultAttrsIntrinsic<[llvm_v4i32_ty], [llvm_any_ty, llvm_i32_ty], [IntrReadMem]>;
def int_spv_resource_getdimensions_ms_xy
- : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty], [IntrReadMem]>;
+ : DefaultAttrsIntrinsic<[llvm_v3i32_ty], [llvm_any_ty], [IntrReadMem]>;
def int_spv_resource_getdimensions_ms_xyz
- : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_any_ty], [IntrReadMem]>;
+ : DefaultAttrsIntrinsic<[llvm_v4i32_ty], [llvm_any_ty], [IntrReadMem]>;
def int_spv_resource_sample
: DefaultAttrsIntrinsic<
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 6a847073c6202..9da8397efc22f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -5028,23 +5028,7 @@ bool SPIRVInstructionSelector::selectGetDimensionsIntrinsic(
*ImageDef, I)) {
return false;
}
- SPIRVTypeInst ScalarResTy = GR.getScalarOrVectorComponentType(ResType);
- bool IsFloat = ScalarResTy->getOpcode() == SPIRV::OpTypeFloat;
-
- Register QueryResultReg =
- IsFloat ? MRI->createVirtualRegister(&SPIRV::iIDRegClass) : ResVReg;
-
- if (!selectImageQuerySize(NewImageReg, QueryResultReg, I, std::nullopt))
- return false;
-
- if (IsFloat) {
- BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpConvertUToF))
- .addDef(ResVReg)
- .addUse(GR.getSPIRVTypeID(ResType))
- .addUse(QueryResultReg)
- .constrainAllUses(TII, TRI, RBI);
- }
- return true;
+ return selectImageQuerySize(NewImageReg, ResVReg, I);
}
bool SPIRVInstructionSelector::selectGetDimensionsLevelsIntrinsic(
@@ -5057,9 +5041,6 @@ bool SPIRVInstructionSelector::selectGetDimensionsLevelsIntrinsic(
return false;
}
- SPIRVTypeInst ScalarResTy = GR.getScalarOrVectorComponentType(ResType);
- bool IsFloat = ScalarResTy->getOpcode() == SPIRV::OpTypeFloat;
-
Register SizeReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
Register LodReg = I.getOperand(3).getReg();
@@ -5079,32 +5060,14 @@ bool SPIRVInstructionSelector::selectGetDimensionsLevelsIntrinsic(
.addUse(NewImageReg)
.constrainAllUses(TII, TRI, RBI);
- SPIRVTypeInst IntResTy = ResType;
- Register CompositeReg = ResVReg;
- if (IsFloat) {
- unsigned NumResComponents = GR.getScalarOrVectorComponentCount(ResType);
- IntResTy =
- NumResComponents == 1
- ? I32Ty
- : GR.getOrCreateSPIRVVectorType(I32Ty, NumResComponents, I, TII);
- CompositeReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
- }
-
BuildMI(*I.getParent(), I, I.getDebugLoc(),
TII.get(SPIRV::OpCompositeConstruct))
- .addDef(CompositeReg)
- .addUse(GR.getSPIRVTypeID(IntResTy))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
.addUse(SizeReg)
.addUse(LevelsReg)
.constrainAllUses(TII, TRI, RBI);
- if (IsFloat) {
- BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpConvertUToF))
- .addDef(ResVReg)
- .addUse(GR.getSPIRVTypeID(ResType))
- .addUse(CompositeReg)
- .constrainAllUses(TII, TRI, RBI);
- }
return true;
}
@@ -5118,15 +5081,12 @@ bool SPIRVInstructionSelector::selectGetDimensionsMSIntrinsic(
return false;
}
- SPIRVTypeInst ScalarResTy = GR.getScalarOrVectorComponentType(ResType);
- bool IsFloat = ScalarResTy->getOpcode() == SPIRV::OpTypeFloat;
-
Register SizeReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
assert(GR.getSPIRVTypeForVReg(NewImageReg)->getOperand(5).getImm() == 1 &&
"OpImageQuerySamples requires a multisampled image");
- if (!selectImageQuerySize(NewImageReg, SizeReg, I, std::nullopt)) {
+ if (!selectImageQuerySize(NewImageReg, SizeReg, I)) {
return false;
}
@@ -5140,32 +5100,14 @@ bool SPIRVInstructionSelector::selectGetDimensionsMSIntrinsic(
.addUse(NewImageReg)
.constrainAllUses(TII, TRI, RBI);
- SPIRVTypeInst IntResTy = ResType;
- Register CompositeReg = ResVReg;
- if (IsFloat) {
- unsigned NumResComponents = GR.getScalarOrVectorComponentCount(ResType);
- IntResTy =
- NumResComponents == 1
- ? I32Ty
- : GR.getOrCreateSPIRVVectorType(I32Ty, NumResComponents, I, TII);
- CompositeReg = MRI->createVirtualRegister(&SPIRV::iIDRegClass);
- }
-
BuildMI(*I.getParent(), I, I.getDebugLoc(),
TII.get(SPIRV::OpCompositeConstruct))
- .addDef(CompositeReg)
- .addUse(GR.getSPIRVTypeID(IntResTy))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
.addUse(SizeReg)
.addUse(SamplesReg)
.constrainAllUses(TII, TRI, RBI);
- if (IsFloat) {
- BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(SPIRV::OpConvertUToF))
- .addDef(ResVReg)
- .addUse(GR.getSPIRVTypeID(ResType))
- .addUse(CompositeReg)
- .constrainAllUses(TII, TRI, RBI);
- }
return true;
}
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensions.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensions.ll
index deca5c9beb2cf..42592e03e6b9a 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensions.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensions.ll
@@ -40,45 +40,45 @@ entry:
; CHECK: %[[img1d_val:[0-9]+]] = OpLoad %[[image1d_s2]]
; CHECK: OpImageQuerySize %[[int]] %[[img1d_val]]
- %res0 = call i32 @llvm.spv.resource.getdimensions.x.i32.tspirv.Image_f32_0_2_0_0_2_0t(target("spirv.Image", float, 0, 2, 0, 0, 2, 0) %img1d)
+ %res0 = call i32 @llvm.spv.resource.getdimensions.x.tspirv.Image_f32_0_2_0_0_2_0t(target("spirv.Image", float, 0, 2, 0, 0, 2, 0) %img1d)
; CHECK: %[[img2d_val:[0-9]+]] = OpLoad %[[image2d_s2]]
; CHECK: OpImageQuerySize %[[v2int]] %[[img2d_val]]
- %res1 = call <2 x i32> @llvm.spv.resource.getdimensions.xy.v2i32.tspirv.Image_f32_1_2_0_0_2_0t(target("spirv.Image", float, 1, 2, 0, 0, 2, 0) %img2d)
+ %res1 = call <2 x i32> @llvm.spv.resource.getdimensions.xy.tspirv.Image_f32_1_2_0_0_2_0t(target("spirv.Image", float, 1, 2, 0, 0, 2, 0) %img2d)
; CHECK: %[[img3d_val:[0-9]+]] = OpLoad %[[image3d_s2]]
; CHECK: OpImageQuerySize %[[v3int]] %[[img3d_val]]
- %res2 = call <3 x i32> @llvm.spv.resource.getdimensions.xyz.v3i32.tspirv.Image_f32_2_2_0_0_2_0t(target("spirv.Image", float, 2, 2, 0, 0, 2, 0) %img3d)
+ %res2 = call <3 x i32> @llvm.spv.resource.getdimensions.xyz.tspirv.Image_f32_2_2_0_0_2_0t(target("spirv.Image", float, 2, 2, 0, 0, 2, 0) %img3d)
; CHECK: %[[img1dlod_val:[0-9]+]] = OpLoad %[[image1d_s1]]
; CHECK: %[[size3:[0-9]+]] = OpImageQuerySizeLod %[[int]] %[[img1dlod_val]] %[[int_0]]
; CHECK: %[[levels3:[0-9]+]] = OpImageQueryLevels %[[int]] %[[img1dlod_val]]
; CHECK: OpCompositeConstruct %[[v2int]] %[[size3]] %[[levels3]]
- %res3 = call <2 x i32> @llvm.spv.resource.getdimensions.levels.x.v2i32.tspirv.Image_f32_0_2_0_0_1_0t(target("spirv.Image", float, 0, 2, 0, 0, 1, 0) %img1dlod, i32 0)
+ %res3 = call <2 x i32> @llvm.spv.resource.getdimensions.levels.x.tspirv.Image_f32_0_2_0_0_1_0t(target("spirv.Image", float, 0, 2, 0, 0, 1, 0) %img1dlod, i32 0)
; CHECK: %[[img2dlod_val:[0-9]+]] = OpLoad %[[image2d_s1]]
; CHECK: %[[size4:[0-9]+]] = OpImageQuerySizeLod %[[v2int]] %[[img2dlod_val]] %[[int_0]]
; CHECK: %[[levels4:[0-9]+]] = OpImageQueryLevels %[[int]] %[[img2dlod_val]]
; CHECK: OpCompositeConstruct %[[v3int]] %[[size4]] %[[levels4]]
- %res4 = call <3 x i32> @llvm.spv.resource.getdimensions.levels.xy.v3i32.tspirv.Image_f32_1_2_0_0_1_0t(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %img2dlod, i32 0)
+ %res4 = call <3 x i32> @llvm.spv.resource.getdimensions.levels.xy.tspirv.Image_f32_1_2_0_0_1_0t(target("spirv.Image", float, 1, 2, 0, 0, 1, 0) %img2dlod, i32 0)
; CHECK: %[[img3dlod_val:[0-9]+]] = OpLoad %[[image3d_s1]]
; CHECK: %[[size5:[0-9]+]] = OpImageQuerySizeLod %[[v3int]] %[[img3dlod_val]] %[[int_0]]
; CHECK: %[[levels5:[0-9]+]] = OpImageQueryLevels %[[int]] %[[img3dlod_val]]
; CHECK: OpCompositeConstruct %[[v4int]] %[[size5]] %[[levels5]]
- %res5 = call <4 x i32> @llvm.spv.resource.getdimensions.levels.xyz.v4i32.tspirv.Image_f32_2_2_0_0_1_0t(target("spirv.Image", float, 2, 2, 0, 0, 1, 0) %img3dlod, i32 0)
+ %res5 = call <4 x i32> @llvm.spv.resource.getdimensions.levels.xyz.tspirv.Image_f32_2_2_0_0_1_0t(target("spirv.Image", float, 2, 2, 0, 0, 1, 0) %img3dlod, i32 0)
; CHECK: %[[imgms_val:[0-9]+]] = OpLoad %[[imagems]]
; CHECK: %[[size6:[0-9]+]] = OpImageQuerySize %[[v2int]] %[[imgms_val]]
; CHECK: %[[samp6:[0-9]+]] = OpImageQuerySamples %[[int]] %[[imgms_val]]
; CHECK: OpCompositeConstruct %[[v3int]] %[[size6]] %[[samp6]]
- %res6 = call <3 x i32> @llvm.spv.resource.getdimensions.ms.xy.v3i32.tspirv.Image_f32_1_2_0_1_1_0t(target("spirv.Image", float, 1, 2, 0, 1, 1, 0) %imgms)
+ %res6 = call <3 x i32> @llvm.spv.resource.getdimensions.ms.xy.tspirv.Image_f32_1_2_0_1_1_0t(target("spirv.Image", float, 1, 2, 0, 1, 1, 0) %imgms)
; CHECK: %[[imgmsarray_val:[0-9]+]] = OpLoad %[[imagemsarray]]
; CHECK: %[[size7:[0-9]+]] = OpImageQuerySize %[[v3int]] %[[imgmsarray_val]]
; CHECK: %[[samp7:[0-9]+]] = OpImageQuerySamples %[[int]] %[[imgmsarray_val]]
; CHECK: OpCompositeConstruct %[[v4int]] %[[size7]] %[[samp7]]
- %res7 = call <4 x i32> @llvm.spv.resource.getdimensions.ms.xyz.v4i32.tspirv.Image_f32_1_2_1_1_1_0t(target("spirv.Image", float, 1, 2, 1, 1, 1, 0) %imgmsarray)
+ %res7 = call <4 x i32> @llvm.spv.resource.getdimensions.ms.xyz.tspirv.Image_f32_1_2_1_1_1_0t(target("spirv.Image", float, 1, 2, 1, 1, 1, 0) %imgmsarray)
ret void
}
@@ -94,13 +94,13 @@ declare target("spirv.Image", float, 2, 2, 0, 0, 1, 0) @llvm.spv.resource.handle
declare target("spirv.Image", float, 1, 2, 0, 1, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_0_1_1_0t(i32, i32, i32, i32, ptr)
declare target("spirv.Image", float, 1, 2, 1, 1, 1, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_1_2_1_1_1_0t(i32, i32, i32, i32, ptr)
-declare i32 @llvm.spv.resource.getdimensions.x.i32.tspirv.Image_f32_0_2_0_0_2_0t(target("spirv.Image", float, 0, 2, 0, 0, 2, 0))
-declare <2 x i32> @llvm.spv.resource.getdimensions.xy.v2i32.tspirv.Image_f32_1_2_0_0_2_0t(target("spirv.Image", float, 1, 2, 0, 0, 2, 0))
-declare <3 x i32> @llvm.spv.resource.getdimensions.xyz.v3i32.tspirv.Image_f32_2_2_0_0_2_0t(target("spirv.Image", float, 2, 2, 0, 0, 2, 0))
+declare i32 @llvm.spv.resource.getdimensions.x.tspirv.Image_f32_0_2_0_0_2_0t(target("spirv.Image", float, 0, 2, 0, 0, 2, 0))
+declare <2 x i32> @llvm.spv.resource.getdimensions.xy.tspirv.Image_f32_1_2_0_0_2_0t(target("spirv.Image", float, 1, 2, 0, 0, 2, 0))
+declare <3 x i32> @llvm.spv.resource.getdimensions.xyz.tspirv.Image_f32_2_2_0_0_2_0t(target("spirv.Image", float, 2, 2, 0, 0, 2, 0))
-declare <2 x i32> @llvm.spv.resource.getdimensions.levels.x.v2i32.tspirv.Image_f32_0_2_0_0_1_0t(target("spirv.Image", float, 0, 2, 0, 0, 1, 0), i32)
-declare <3 x i32> @llvm.spv.resource.getdimensions.levels.xy.v3i32.tspirv.Image_f32_1_2_0_0_1_0t(target("spirv.Image", float, 1, 2, 0, 0, 1, 0), i32)
-declare <4 x i32> @llvm.spv.resource.getdimensions.levels.xyz.v4i32.tspirv.Image_f32_2_2_0_0_1_0t(target("spirv.Image", float, 2, 2, 0, 0, 1, 0), i32)
+declare <2 x i32> @llvm.spv.resource.getdimensions.levels.x.tspirv.Image_f32_0_2_0_0_1_0t(target("spirv.Image", float, 0, 2, 0, 0, 1, 0), i32)
+declare <3 x i32> @llvm.spv.resource.getdimensions.levels.xy.tspirv.Image_f32_1_2_0_0_1_0t(target("spirv.Image", float, 1, 2, 0, 0, 1, 0), i32)
+declare <4 x i32> @llvm.spv.resource.getdimensions.levels.xyz.tspirv.Image_f32_2_2_0_0_1_0t(target("spirv.Image", float, 2, 2, 0, 0, 1, 0), i32)
-declare <3 x i32> @llvm.spv.resource.getdimensions.ms.xy.v3i32.tspirv.Image_f32_1_2_0_1_1_0t(target("spirv.Image", float, 1, 2, 0, 1, 1, 0))
-declare <4 x i32> @llvm.spv.resource.getdimensions.ms.xyz.v4i32.tspirv.Image_f32_1_2_1_1_1_0t(target("spirv.Image", float, 1, 2, 1, 1, 1, 0))
+declare <3 x i32> @llvm.spv.resource.getdimensions.ms.xy.tspirv.Image_f32_1_2_0_1_1_0t(target("spirv.Image", float, 1, 2, 0, 1, 1, 0))
+declare <4 x i32> @llvm.spv.resource.getdimensions.ms.xyz.tspirv.Image_f32_1_2_1_1_1_0t(target("spirv.Image", float, 1, 2, 1, 1, 1, 0))
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensionsFloat.ll b/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensionsFloat.ll
deleted file mode 100644
index 7998d2c7814a0..0000000000000
--- a/llvm/test/CodeGen/SPIRV/hlsl-resources/GetDimensionsFloat.ll
+++ /dev/null
@@ -1,25 +0,0 @@
-; RUN: llc -O0 -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 --target-env vulkan1.3 %}
-
-; CHECK-DAG: [[FLOAT_TY:%[0-9]+]] = OpTypeFloat 32
-; CHECK-DAG: [[IMG_TY:%[0-9]+]] = OpTypeImage [[FLOAT_TY]] 1D 2 0 0 2 Unknown
-; CHECK-DAG: [[INT_TY:%[0-9]+]] = OpTypeInt 32 0
-; CHECK-DAG: [[PTR_IMG_TY:%[0-9]+]] = OpTypePointer UniformConstant [[IMG_TY]]
-; CHECK: [[VAR:%[0-9]+]] = OpVariable [[PTR_IMG_TY]] UniformConstant
-; CHECK: [[LOAD:%[0-9]+]] = OpLoad [[IMG_TY]] [[VAR]]
-; CHECK: [[QUERY:%[0-9]+]] = OpImageQuerySize [[INT_TY]] [[LOAD]]
-; CHECK: {{%[0-9]+}} = OpConvertUToF [[FLOAT_TY]] [[QUERY]]
-
- at .str1 = private unnamed_addr constant [6 x i8] c"img1d\00", align 1
-
-define void @main() #0 {
-entry:
- %img1d = tail call target("spirv.Image", float, 0, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_0_2_0_0_2_0t(i32 0, i32 0, i32 1, i32 0, ptr @.str1)
- %res0 = call float @llvm.spv.resource.getdimensions.x.f32.tspirv.Image_f32_0_2_0_0_2_0t(target("spirv.Image", float, 0, 2, 0, 0, 2, 0) %img1d)
- ret void
-}
-
-attributes #0 = { "hlsl.shader"="pixel" }
-
-declare target("spirv.Image", float, 0, 2, 0, 0, 2, 0) @llvm.spv.resource.handlefrombinding.tspirv.Image_f32_0_2_0_0_2_0t(i32, i32, i32, i32, ptr)
-declare float @llvm.spv.resource.getdimensions.x.f32.tspirv.Image_f32_0_2_0_0_2_0t(target("spirv.Image", float, 0, 2, 0, 0, 2, 0))
More information about the llvm-branch-commits
mailing list