[llvm] [AMDGPU] Fold image load/store with known-zero slice index to non-arrayed form (PR #214744)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 7 07:46:22 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Barbara Mitic (barbara-amd)

<details>
<summary>Changes</summary>

Fold image load/store with known-zero slice index to non-arrayed form

When an arrayed image load or store uses a statically-known array slice of 0, the slice coordinate is redundant: slice 0 is the base layer, so the address matches the corresponding non-arrayed access. Today the compiler still materializes the constant-zero slice into a VGPR and emits the arrayed instruction.
This change folds such accesses to their non-arrayed form. The main benefit is that the zero slice no longer has to be materialized, so the extra v_mov and the address VGPR it occupied goes away. The fold applies to plain image loads and stores for 2D_ARRAY -> 2D, 1D_ARRAY -> 1D, and 2D_MSAA_ARRAY -> 2D_MSAA.

Example:

Before:
v_dual_mov_b32 v6, 0 :: v_dual_and_b32 v1, 0xffff, v16
v_bfe_i32 v7, v21, 0, 16
v_bfe_i32 v8, v22, 0, 16
...
image_store v[0:1], [v4, v5, v6], s[0:7] dmask:0x7 dim:SQ_RSRC_IMG_2D_ARRAY d16
image_store v[2:3], [v7, v8, v6], s[0:7] dmask:0x7 dim:SQ_RSRC_IMG_2D_ARRAY d16

After:
v_and_b32_e32 v1, 0xffff, v16
v_bfe_i32 v6, v21, 0, 16
v_bfe_i32 v7, v22, 0, 16
...
image_store v[0:1], [v4, v5], s[0:7] dmask:0x7 dim:SQ_RSRC_IMG_2D d16
image_store v[2:3], [v6, v7], s[0:7] dmask:0x7 dim:SQ_RSRC_IMG_2D d16

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


5 Files Affected:

- (modified) llvm/include/llvm/IR/IntrinsicsAMDGPU.td (+7) 
- (modified) llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp (+27-6) 
- (modified) llvm/lib/Target/AMDGPU/MIMGInstructions.td (+3-1) 
- (modified) llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h (+1) 
- (added) llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-simplify-image-array-zero-slice.ll (+181) 


``````````diff
diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
index 9c57b4d343fc6..be939f8e6531e 100644
--- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
+++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td
@@ -989,6 +989,10 @@ class AMDGPUDimProps<bits<3> enc, string name, string asmsuffix,
   bit DA = 0; // DA bit in MIMG encoding
   bit MSAA = msaa;
 
+  // The corresponding non-arrayed dim, e.g. 2D_ARRAY -> 2D. Defaults to Dim.
+  // The arrayed dims override it below.
+  AMDGPUDimProps NonArrayDim = Dim;
+
   list<AMDGPUArg> CoordSliceArgs =
     makeArgList<!listconcat(coord_names, slice_names), llvm_anyfloat_ty>.ret;
   list<AMDGPUArg> CoordSliceIntArgs =
@@ -1007,11 +1011,14 @@ def AMDGPUDim2D : AMDGPUDimProps<0x1, "2d", "2D", ["s", "t"], []>;
 def AMDGPUDim3D : AMDGPUDimProps<0x2, "3d", "3D", ["s", "t", "r"], []>;
 let DA = 1 in {
   def AMDGPUDimCube : AMDGPUDimProps<0x3, "cube", "CUBE", ["s", "t"], ["face"]>;
+  let NonArrayDim = AMDGPUDim1D in
   def AMDGPUDim1DArray : AMDGPUDimProps<0x4, "1darray", "1D_ARRAY", ["s"], ["slice"]>;
+  let NonArrayDim = AMDGPUDim2D in
   def AMDGPUDim2DArray : AMDGPUDimProps<0x5, "2darray", "2D_ARRAY", ["s", "t"], ["slice"]>;
 }
 def AMDGPUDim2DMsaa : AMDGPUDimProps<0x6, "2dmsaa", "2D_MSAA", ["s", "t"], ["fragid"], 1>;
 let DA = 1 in {
+  let NonArrayDim = AMDGPUDim2DMsaa in
   def AMDGPUDim2DArrayMsaa : AMDGPUDimProps<0x7, "2darraymsaa", "2D_MSAA_ARRAY", ["s", "t"], ["slice", "fragid"], 1>;
 }
 
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
index 7e88334f70993..95143f27aacf3 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstCombineIntrinsic.cpp
@@ -182,6 +182,9 @@ static std::optional<Instruction *>
 simplifyAMDGCNImageIntrinsic(const GCNSubtarget *ST,
                              const AMDGPU::ImageDimIntrinsicInfo *ImageDimIntr,
                              IntrinsicInst &II, InstCombiner &IC) {
+  const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
+      AMDGPU::getMIMGBaseOpcodeInfo(ImageDimIntr->BaseOpcode);
+
   // Optimize _L to _LZ when _L is zero
   if (const auto *LZMappingInfo =
           AMDGPU::getMIMGLZMappingInfo(ImageDimIntr->BaseOpcode)) {
@@ -251,12 +254,31 @@ simplifyAMDGCNImageIntrinsic(const GCNSubtarget *ST,
     }
   }
 
+  // Optimize the arrayed dim away when the array slice is zero, since slice 0
+  // is the base layer. Restricted to plain image loads and stores for now.
+  const AMDGPU::MIMGDimInfo *DimInfo =
+      AMDGPU::getMIMGDimInfo(ImageDimIntr->Dim);
+  if (!BaseOpcode->Atomic && !BaseOpcode->Sampler && BaseOpcode->Coordinates &&
+      DimInfo->NonArrayDim != ImageDimIntr->Dim) {
+    // Address is [coords..., slice, (fragid)] plus an optional lod/clamp/mip,
+    // so index from CoordStart.
+    unsigned SliceIndex = ImageDimIntr->CoordStart + DimInfo->NumCoords - 1 -
+                          (DimInfo->MSAA ? 1 : 0);
+    auto *ConstantSlice = dyn_cast<ConstantInt>(II.getOperand(SliceIndex));
+    if (ConstantSlice && ConstantSlice->isZero()) {
+      if (const AMDGPU::ImageDimIntrinsicInfo *NewImageDimIntr =
+              AMDGPU::getImageDimIntrinsicByBaseOpcode(ImageDimIntr->BaseOpcode,
+                                                       DimInfo->NonArrayDim)) {
+        return modifyIntrinsicCall(II, II, NewImageDimIntr->Intr, IC,
+                                   [&](auto &Args, auto &ArgTys) {
+                                     Args.erase(Args.begin() + SliceIndex);
+                                   });
+      }
+    }
+  }
+
   // Try to use D16
   if (ST->hasD16Images()) {
-
-    const AMDGPU::MIMGBaseOpcodeInfo *BaseOpcode =
-        AMDGPU::getMIMGBaseOpcodeInfo(ImageDimIntr->BaseOpcode);
-
     if (BaseOpcode->HasD16) {
 
       // If the only use of image intrinsic is a fptrunc (with conversion to
@@ -346,8 +368,7 @@ simplifyAMDGCNImageIntrinsic(const GCNSubtarget *ST,
 
   // Address is interpreted as float if the instruction has a sampler or as
   // unsigned int if there is no sampler.
-  bool HasSampler =
-      AMDGPU::getMIMGBaseOpcodeInfo(ImageDimIntr->BaseOpcode)->Sampler;
+  bool HasSampler = BaseOpcode->Sampler;
   bool FloatCoord = false;
   // true means derivatives can be converted to 16 bit, coordinates not
   bool OnlyDerivatives = false;
diff --git a/llvm/lib/Target/AMDGPU/MIMGInstructions.td b/llvm/lib/Target/AMDGPU/MIMGInstructions.td
index cb554073f6398..1a4cd39cabfff 100644
--- a/llvm/lib/Target/AMDGPU/MIMGInstructions.td
+++ b/llvm/lib/Target/AMDGPU/MIMGInstructions.td
@@ -80,8 +80,10 @@ def MIMGDim : GenericEnum {
 def MIMGDimInfoTable : GenericTable {
   let FilterClass = "AMDGPUDimProps";
   let CppTypeName = "MIMGDimInfo";
-  let Fields = ["Dim", "NumCoords", "NumGradients", "MSAA", "DA", "Encoding", "AsmSuffix"];
+  let Fields = ["Dim", "NonArrayDim", "NumCoords", "NumGradients", "MSAA", "DA",
+                "Encoding", "AsmSuffix"];
   string TypeOf_Dim = "MIMGDim";
+  string TypeOf_NonArrayDim = "MIMGDim";
 
   let PrimaryKey = ["Dim"];
   let PrimaryKeyName = "getMIMGDimInfo";
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
index 44476d4d555c0..dd76ae0c3af99 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
@@ -410,6 +410,7 @@ const MIMGBaseOpcodeInfo *getMIMGBaseOpcodeInfo(unsigned BaseOpcode);
 
 struct MIMGDimInfo {
   MIMGDim Dim;
+  MIMGDim NonArrayDim;
   uint8_t NumCoords;
   uint8_t NumGradients;
   bool MSAA;
diff --git a/llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-simplify-image-array-zero-slice.ll b/llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-simplify-image-array-zero-slice.ll
new file mode 100644
index 0000000000000..98b196b9848af
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/AMDGPU/amdgcn-simplify-image-array-zero-slice.ll
@@ -0,0 +1,181 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -mcpu=gfx1201 -S -passes=instcombine -mtriple=amdgcn-amd-amdhsa %s | FileCheck %s
+
+define amdgpu_ps void @store_1darray_zero_slice(<8 x i32> inreg %rsrc, <4 x float> %vdata, i32 %s) #0 {
+; CHECK-LABEL: define amdgpu_ps void @store_1darray_zero_slice(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], <4 x float> [[VDATA:%.*]], i32 [[S:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT:    call void @llvm.amdgcn.image.store.1d.v4f32.i32.v8i32(<4 x float> [[VDATA]], i32 15, i32 [[S]], <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.amdgcn.image.store.1darray.v4f32.i32.v8i32(<4 x float> %vdata, i32 15, i32 %s, i32 0, <8 x i32> %rsrc, i32 0, i32 0)
+  ret void
+}
+
+define amdgpu_ps void @store_2darray_zero_slice(<8 x i32> inreg %rsrc, <4 x float> %vdata, i32 %s, i32 %t) #0 {
+; CHECK-LABEL: define amdgpu_ps void @store_2darray_zero_slice(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], <4 x float> [[VDATA:%.*]], i32 [[S:%.*]], i32 [[T:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    call void @llvm.amdgcn.image.store.2d.v4f32.i32.v8i32(<4 x float> [[VDATA]], i32 15, i32 [[S]], i32 [[T]], <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.amdgcn.image.store.2darray.v4f32.i32.v8i32(<4 x float> %vdata, i32 15, i32 %s, i32 %t, i32 0, <8 x i32> %rsrc, i32 0, i32 0)
+  ret void
+}
+
+define amdgpu_ps void @store_2darraymsaa_zero_slice(<8 x i32> inreg %rsrc, <4 x float> %vdata, i32 %s, i32 %t, i32 %fragid) #0 {
+; CHECK-LABEL: define amdgpu_ps void @store_2darraymsaa_zero_slice(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], <4 x float> [[VDATA:%.*]], i32 [[S:%.*]], i32 [[T:%.*]], i32 [[FRAGID:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    call void @llvm.amdgcn.image.store.2dmsaa.v4f32.i32.v8i32(<4 x float> [[VDATA]], i32 15, i32 [[S]], i32 [[T]], i32 [[FRAGID]], <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.amdgcn.image.store.2darraymsaa.v4f32.i32.v8i32(<4 x float> %vdata, i32 15, i32 %s, i32 %t, i32 0, i32 %fragid, <8 x i32> %rsrc, i32 0, i32 0)
+  ret void
+}
+
+define amdgpu_ps void @store_mip_2darray_zero_slice_nonzero_mip(<8 x i32> inreg %rsrc, <4 x float> %vdata, i32 %s, i32 %t) #0 {
+; CHECK-LABEL: define amdgpu_ps void @store_mip_2darray_zero_slice_nonzero_mip(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], <4 x float> [[VDATA:%.*]], i32 [[S:%.*]], i32 [[T:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    call void @llvm.amdgcn.image.store.mip.2d.v4f32.i32.v8i32(<4 x float> [[VDATA]], i32 15, i32 [[S]], i32 [[T]], i32 2, <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.amdgcn.image.store.mip.2darray.v4f32.i32.v8i32(<4 x float> %vdata, i32 15, i32 %s, i32 %t, i32 0, i32 2, <8 x i32> %rsrc, i32 0, i32 0)
+  ret void
+}
+
+define amdgpu_ps void @store_2darray_zero_slice_a16(<8 x i32> inreg %rsrc, <4 x float> %vdata, i16 %s, i16 %t) #0 {
+; CHECK-LABEL: define amdgpu_ps void @store_2darray_zero_slice_a16(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], <4 x float> [[VDATA:%.*]], i16 [[S:%.*]], i16 [[T:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    call void @llvm.amdgcn.image.store.2d.v4f32.i16.v8i32(<4 x float> [[VDATA]], i32 15, i16 [[S]], i16 [[T]], <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.amdgcn.image.store.2darray.v4f32.i16.v8i32(<4 x float> %vdata, i32 15, i16 %s, i16 %t, i16 0, <8 x i32> %rsrc, i32 0, i32 0)
+  ret void
+}
+
+define amdgpu_ps <4 x float> @load_1darray_zero_slice(<8 x i32> inreg %rsrc, i32 %s) #0 {
+; CHECK-LABEL: define amdgpu_ps <4 x float> @load_1darray_zero_slice(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], i32 [[S:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[V:%.*]] = call <4 x float> @llvm.amdgcn.image.load.1d.v4f32.i32.v8i32(i32 15, i32 [[S]], <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret <4 x float> [[V]]
+;
+  %v = call <4 x float> @llvm.amdgcn.image.load.1darray.v4f32.i32.v8i32(i32 15, i32 %s, i32 0, <8 x i32> %rsrc, i32 0, i32 0)
+  ret <4 x float> %v
+}
+
+define amdgpu_ps <4 x float> @load_2darray_zero_slice(<8 x i32> inreg %rsrc, i32 %s, i32 %t) #0 {
+; CHECK-LABEL: define amdgpu_ps <4 x float> @load_2darray_zero_slice(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], i32 [[S:%.*]], i32 [[T:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[V:%.*]] = call <4 x float> @llvm.amdgcn.image.load.2d.v4f32.i32.v8i32(i32 15, i32 [[S]], i32 [[T]], <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret <4 x float> [[V]]
+;
+  %v = call <4 x float> @llvm.amdgcn.image.load.2darray.v4f32.i32.v8i32(i32 15, i32 %s, i32 %t, i32 0, <8 x i32> %rsrc, i32 0, i32 0)
+  ret <4 x float> %v
+}
+
+define amdgpu_ps <4 x float> @load_2darraymsaa_zero_slice(<8 x i32> inreg %rsrc, i32 %s, i32 %t, i32 %fragid) #0 {
+; CHECK-LABEL: define amdgpu_ps <4 x float> @load_2darraymsaa_zero_slice(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], i32 [[S:%.*]], i32 [[T:%.*]], i32 [[FRAGID:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[V:%.*]] = call <4 x float> @llvm.amdgcn.image.load.2dmsaa.v4f32.i32.v8i32(i32 15, i32 [[S]], i32 [[T]], i32 [[FRAGID]], <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret <4 x float> [[V]]
+;
+  %v = call <4 x float> @llvm.amdgcn.image.load.2darraymsaa.v4f32.i32.v8i32(i32 15, i32 %s, i32 %t, i32 0, i32 %fragid, <8 x i32> %rsrc, i32 0, i32 0)
+  ret <4 x float> %v
+}
+
+define amdgpu_ps <4 x float> @msaa_load_x_2darraymsaa_zero_slice(<8 x i32> inreg %rsrc, i32 %s, i32 %t, i32 %fragid) #0 {
+; CHECK-LABEL: define amdgpu_ps <4 x float> @msaa_load_x_2darraymsaa_zero_slice(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], i32 [[S:%.*]], i32 [[T:%.*]], i32 [[FRAGID:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[V:%.*]] = call <4 x float> @llvm.amdgcn.image.msaa.load.x.2dmsaa.v4f32.i32.v8i32(i32 15, i32 [[S]], i32 [[T]], i32 [[FRAGID]], <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret <4 x float> [[V]]
+;
+  %v = call <4 x float> @llvm.amdgcn.image.msaa.load.x.2darraymsaa.v4f32.i32.v8i32(i32 15, i32 %s, i32 %t, i32 0, i32 %fragid, <8 x i32> %rsrc, i32 0, i32 0)
+  ret <4 x float> %v
+}
+
+define amdgpu_ps void @store_2darray_nonzero_slice(<8 x i32> inreg %rsrc, <4 x float> %vdata, i32 %s, i32 %t) #0 {
+; CHECK-LABEL: define amdgpu_ps void @store_2darray_nonzero_slice(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], <4 x float> [[VDATA:%.*]], i32 [[S:%.*]], i32 [[T:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    call void @llvm.amdgcn.image.store.2darray.v4f32.i32.v8i32(<4 x float> [[VDATA]], i32 15, i32 [[S]], i32 [[T]], i32 1, <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.amdgcn.image.store.2darray.v4f32.i32.v8i32(<4 x float> %vdata, i32 15, i32 %s, i32 %t, i32 1, <8 x i32> %rsrc, i32 0, i32 0)
+  ret void
+}
+
+define amdgpu_ps void @store_2darray_variable_slice(<8 x i32> inreg %rsrc, <4 x float> %vdata, i32 %s, i32 %t, i32 %slice) #0 {
+; CHECK-LABEL: define amdgpu_ps void @store_2darray_variable_slice(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], <4 x float> [[VDATA:%.*]], i32 [[S:%.*]], i32 [[T:%.*]], i32 [[SLICE:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    call void @llvm.amdgcn.image.store.2darray.v4f32.i32.v8i32(<4 x float> [[VDATA]], i32 15, i32 [[S]], i32 [[T]], i32 [[SLICE]], <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.amdgcn.image.store.2darray.v4f32.i32.v8i32(<4 x float> %vdata, i32 15, i32 %s, i32 %t, i32 %slice, <8 x i32> %rsrc, i32 0, i32 0)
+  ret void
+}
+
+define amdgpu_ps void @store_cube_zero_face(<8 x i32> inreg %rsrc, <4 x float> %vdata, i32 %s, i32 %t) #0 {
+; CHECK-LABEL: define amdgpu_ps void @store_cube_zero_face(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], <4 x float> [[VDATA:%.*]], i32 [[S:%.*]], i32 [[T:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    call void @llvm.amdgcn.image.store.cube.v4f32.i32.v8i32(<4 x float> [[VDATA]], i32 15, i32 [[S]], i32 [[T]], i32 0, <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.amdgcn.image.store.cube.v4f32.i32.v8i32(<4 x float> %vdata, i32 15, i32 %s, i32 %t, i32 0, <8 x i32> %rsrc, i32 0, i32 0)
+  ret void
+}
+
+define amdgpu_ps void @store_3d_zero_r(<8 x i32> inreg %rsrc, <4 x float> %vdata, i32 %s, i32 %t) #0 {
+; CHECK-LABEL: define amdgpu_ps void @store_3d_zero_r(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], <4 x float> [[VDATA:%.*]], i32 [[S:%.*]], i32 [[T:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    call void @llvm.amdgcn.image.store.3d.v4f32.i32.v8i32(<4 x float> [[VDATA]], i32 15, i32 [[S]], i32 [[T]], i32 0, <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.amdgcn.image.store.3d.v4f32.i32.v8i32(<4 x float> %vdata, i32 15, i32 %s, i32 %t, i32 0, <8 x i32> %rsrc, i32 0, i32 0)
+  ret void
+}
+
+define amdgpu_ps <4 x float> @getresinfo_2darray_zero_mip(<8 x i32> inreg %rsrc) #0 {
+; CHECK-LABEL: define amdgpu_ps <4 x float> @getresinfo_2darray_zero_mip(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[V:%.*]] = call <4 x float> @llvm.amdgcn.image.getresinfo.2darray.v4f32.i16.v8i32(i32 15, i16 0, <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret <4 x float> [[V]]
+;
+  %v = call <4 x float> @llvm.amdgcn.image.getresinfo.2darray.v4f32.i32.v8i32(i32 15, i32 0, <8 x i32> %rsrc, i32 0, i32 0)
+  ret <4 x float> %v
+}
+
+define amdgpu_ps <4 x float> @sample_cl_2darray_zero_slice_zero_clamp(<8 x i32> inreg %rsrc, <4 x i32> inreg %samp, float %s, float %t) #0 {
+; CHECK-LABEL: define amdgpu_ps <4 x float> @sample_cl_2darray_zero_slice_zero_clamp(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], <4 x i32> inreg [[SAMP:%.*]], float [[S:%.*]], float [[T:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[V:%.*]] = call <4 x float> @llvm.amdgcn.image.sample.cl.2darray.v4f32.f32.v8i32.v4i32(i32 15, float [[S]], float [[T]], float 0.000000e+00, float 0.000000e+00, <8 x i32> [[RSRC]], <4 x i32> [[SAMP]], i1 false, i32 0, i32 0)
+; CHECK-NEXT:    ret <4 x float> [[V]]
+;
+  %v = call <4 x float> @llvm.amdgcn.image.sample.cl.2darray.v4f32.f32.v8i32.v4i32(i32 15, float %s, float %t, float 0.0, float 0.0, <8 x i32> %rsrc, <4 x i32> %samp, i1 false, i32 0, i32 0)
+  ret <4 x float> %v
+}
+
+define amdgpu_ps i32 @atomic_add_2darray_zero_slice(<8 x i32> inreg %rsrc, i32 %data, i32 %s, i32 %t) #0 {
+; CHECK-LABEL: define amdgpu_ps i32 @atomic_add_2darray_zero_slice(
+; CHECK-SAME: <8 x i32> inreg [[RSRC:%.*]], i32 [[DATA:%.*]], i32 [[S:%.*]], i32 [[T:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT:    [[V:%.*]] = call i32 @llvm.amdgcn.image.atomic.add.2darray.i32.i32.v8i32(i32 [[DATA]], i32 [[S]], i32 [[T]], i32 0, <8 x i32> [[RSRC]], i32 0, i32 0)
+; CHECK-NEXT:    ret i32 [[V]]
+;
+  %v = call i32 @llvm.amdgcn.image.atomic.add.2darray.i32.i32.v8i32(i32 %data, i32 %s, i32 %t, i32 0, <8 x i32> %rsrc, i32 0, i32 0)
+  ret i32 %v
+}
+
+declare void @llvm.amdgcn.image.store.1darray.v4f32.i32.v8i32(<4 x float>, i32, i32, i32, <8 x i32>, i32, i32) #0
+declare void @llvm.amdgcn.image.store.2darray.v4f32.i32.v8i32(<4 x float>, i32, i32, i32, i32, <8 x i32>, i32, i32) #0
+declare void @llvm.amdgcn.image.store.2darray.v4f32.i16.v8i32(<4 x float>, i32, i16, i16, i16, <8 x i32>, i32, i32) #0
+declare void @llvm.amdgcn.image.store.2darraymsaa.v4f32.i32.v8i32(<4 x float>, i32, i32, i32, i32, i32, <8 x i32>, i32, i32) #0
+declare void @llvm.amdgcn.image.store.mip.2darray.v4f32.i32.v8i32(<4 x float>, i32, i32, i32, i32, i32, <8 x i32>, i32, i32) #0
+declare void @llvm.amdgcn.image.store.cube.v4f32.i32.v8i32(<4 x float>, i32, i32, i32, i32, <8 x i32>, i32, i32) #0
+declare void @llvm.amdgcn.image.store.3d.v4f32.i32.v8i32(<4 x float>, i32, i32, i32, i32, <8 x i32>, i32, i32) #0
+declare <4 x float> @llvm.amdgcn.image.load.1darray.v4f32.i32.v8i32(i32, i32, i32, <8 x i32>, i32, i32) #1
+declare <4 x float> @llvm.amdgcn.image.load.2darray.v4f32.i32.v8i32(i32, i32, i32, i32, <8 x i32>, i32, i32) #1
+declare <4 x float> @llvm.amdgcn.image.load.2darraymsaa.v4f32.i32.v8i32(i32, i32, i32, i32, i32, <8 x i32>, i32, i32) #1
+declare <4 x float> @llvm.amdgcn.image.msaa.load.x.2darraymsaa.v4f32.i32.v8i32(i32, i32, i32, i32, i32, <8 x i32>, i32, i32) #1
+declare <4 x float> @llvm.amdgcn.image.getresinfo.2darray.v4f32.i32.v8i32(i32, i32, <8 x i32>, i32, i32) #1
+declare <4 x float> @llvm.amdgcn.image.sample.cl.2darray.v4f32.f32.v8i32.v4i32(i32, float, float, float, float, <8 x i32>, <4 x i32>, i1, i32, i32) #1
+declare i32 @llvm.amdgcn.image.atomic.add.2darray.i32.i32.v8i32(i32, i32, i32, i32, <8 x i32>, i32, i32) #2
+
+attributes #0 = { nounwind }
+attributes #1 = { nounwind readonly }
+attributes #2 = { nounwind }

``````````

</details>


https://github.com/llvm/llvm-project/pull/214744


More information about the llvm-commits mailing list