[llvm] [SPIRV] Add OpAccessChain instruction support (PR #66253)

Nathan Gauër via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 26 05:59:23 PDT 2023


https://github.com/Keenuts updated https://github.com/llvm/llvm-project/pull/66253

>From 15176ba50f89b6f70910773e08fc94d24483d908 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brioche at google.com>
Date: Tue, 12 Sep 2023 18:40:28 +0200
Subject: [PATCH 1/3] [SPIRV] Add OpAccessChain to instruction selector
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Graphical SPIR-V cannot use OpPtrAccessChain, so we need
to add support for OpAccessChain.

We generate the InBounds variant depending on the LLVM IR.

TODO: figure out if I can only rely on the IR's InBounds marker,
or if the SPIR-V spec has is more restrictive.

Signed-off-by: Nathan Gauër <brioche at google.com>
---
 llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp |  2 +-
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 17 ++++--
 .../CodeGen/SPIRV/logical-access-chain.ll     | 21 +++++++
 .../CodeGen/SPIRV/logical-struct-access.ll    | 59 +++++++++++++++++++
 4 files changed, 92 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/logical-access-chain.ll
 create mode 100644 llvm/test/CodeGen/SPIRV/logical-struct-access.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index a05e108b8591a37..610d9a033aeea64 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -413,7 +413,7 @@ void SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I) {
     EltTyConst = Constant::getNullValue(AI->getAllocatedType());
     AddressSpace = AI->getAddressSpace();
   } else if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
-    EltTyConst = Constant::getNullValue(GEP->getSourceElementType());
+    EltTyConst = Constant::getNullValue(GEP->getResultElementType());
     AddressSpace = GEP->getPointerAddressSpace();
   } else {
     llvm_unreachable("Unexpected instruction!");
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index afa34ff3ce1fa40..4e49386415118dd 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1298,18 +1298,23 @@ bool SPIRVInstructionSelector::selectExtractElt(Register ResVReg,
 bool SPIRVInstructionSelector::selectGEP(Register ResVReg,
                                          const SPIRVType *ResType,
                                          MachineInstr &I) const {
-  // In general we should also support OpAccessChain instrs here (i.e. not
-  // PtrAccessChain) but SPIRV-LLVM Translator doesn't emit them at all and so
-  // do we to stay compliant with its test and more importantly consumers.
-  unsigned Opcode = I.getOperand(2).getImm() ? SPIRV::OpInBoundsPtrAccessChain
-                                             : SPIRV::OpPtrAccessChain;
+  const bool isGEPInBounds = I.getOperand(2).getImm();
+
+  // OpAccessChain could be used for OpenCL, but the SPIRV-LLVM Translator only relies
+  // on PtrAccessChain, so we'll try not to deviate. For Vulkan however, we have to use
+  // Op[InBounds]AccessChain.
+  const unsigned Opcode = STI.isVulkanEnv()
+                   ? (isGEPInBounds ? SPIRV::OpInBoundsAccessChain    : SPIRV::OpAccessChain)
+                   : (isGEPInBounds ? SPIRV::OpInBoundsPtrAccessChain : SPIRV::OpPtrAccessChain);
+
   auto Res = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(Opcode))
                  .addDef(ResVReg)
                  .addUse(GR.getSPIRVTypeID(ResType))
                  // Object to get a pointer to.
                  .addUse(I.getOperand(3).getReg());
   // Adding indices.
-  for (unsigned i = 4; i < I.getNumExplicitOperands(); ++i)
+  const unsigned StartingIndex = (Opcode == SPIRV::OpAccessChain || Opcode == SPIRV::OpInBoundsAccessChain) ? 5 : 4;
+  for (unsigned i = StartingIndex; i < I.getNumExplicitOperands(); ++i)
     Res.addUse(I.getOperand(i).getReg());
   return Res.constrainAllUses(TII, TRI, RBI);
 }
diff --git a/llvm/test/CodeGen/SPIRV/logical-access-chain.ll b/llvm/test/CodeGen/SPIRV/logical-access-chain.ll
new file mode 100644
index 000000000000000..5fe60e8bbabb162
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/logical-access-chain.ll
@@ -0,0 +1,21 @@
+; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+
+; CHECK:      [[uint:%[0-9]+]] = OpTypeInt 32 0
+; CHECK:     [[uint2:%[0-9]+]] = OpTypeVector [[uint]] 2
+; CHECK:    [[uint_1:%[0-9]+]] = OpConstant [[uint]] 1
+; CHECK:  [[ptr_uint:%[0-9]+]] = OpTypePointer Function [[uint]]
+; CHECK: [[ptr_uint2:%[0-9]+]] = OpTypePointer Function [[uint2]]
+
+define void @main() #1 {
+entry:
+  %0 = alloca <2 x i32>, align 4
+; CHECK: [[var:%[0-9]+]] = OpVariable [[ptr_uint2]] Function
+
+  %1 = getelementptr <2 x i32>, ptr %0, i32 0, i32 1
+; CHECK: {{%[0-9]+}} = OpAccessChain [[ptr_uint]] [[var]] [[uint_1]]
+
+  ret void
+}
+
+attributes #1 = { "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" }
+
diff --git a/llvm/test/CodeGen/SPIRV/logical-struct-access.ll b/llvm/test/CodeGen/SPIRV/logical-struct-access.ll
new file mode 100644
index 000000000000000..ba49b80ce5d1cbd
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/logical-struct-access.ll
@@ -0,0 +1,59 @@
+; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+
+; CHECK: [[uint:%[0-9]+]] = OpTypeInt 32 0
+
+%A = type {
+  i32,
+  i32
+}
+; CHECK:    [[A:%[0-9]+]] = OpTypeStruct [[uint]] [[uint]]
+
+%B = type {
+  %A,
+  i32,
+  %A
+}
+; CHECK:    [[B:%[0-9]+]] = OpTypeStruct [[A]] [[uint]] [[A]]
+
+; CHECK: [[uint_0:%[0-9]+]] = OpConstant [[uint]] 0
+; CHECK: [[uint_1:%[0-9]+]] = OpConstant [[uint]] 1
+; CHECK: [[uint_2:%[0-9]+]] = OpConstant [[uint]] 2
+
+; CHECK: [[ptr_uint:%[0-9]+]] = OpTypePointer Function [[uint]]
+; CHECK:    [[ptr_A:%[0-9]+]] = OpTypePointer Function [[A]]
+; CHECK:    [[ptr_B:%[0-9]+]] = OpTypePointer Function [[B]]
+
+define void @main() #1 {
+entry:
+  %0 = alloca %B, align 4
+; CHECK: [[tmp:%[0-9]+]] = OpVariable [[ptr_B]] Function
+
+  %1 = getelementptr %B, ptr %0, i32 0, i32 0
+; CHECK: {{%[0-9]+}} = OpAccessChain [[ptr_A]] [[tmp]] [[uint_0]]
+  %2 = getelementptr inbounds %B, ptr %0, i32 0, i32 0
+; CHECK: {{%[0-9]+}} = OpInBoundsAccessChain [[ptr_A]] [[tmp]] [[uint_0]]
+
+  %3 = getelementptr %B, ptr %0, i32 0, i32 1
+; CHECK: {{%[0-9]+}} = OpAccessChain [[ptr_uint]] [[tmp]] [[uint_1]]
+  %4 = getelementptr inbounds %B, ptr %0, i32 0, i32 1
+; CHECK: {{%[0-9]+}} = OpInBoundsAccessChain [[ptr_uint]] [[tmp]] [[uint_1]]
+
+  %5 = getelementptr %B, ptr %0, i32 0, i32 2
+; CHECK: {{%[0-9]+}} = OpAccessChain [[ptr_A]] [[tmp]] [[uint_2]]
+  %6 = getelementptr inbounds %B, ptr %0, i32 0, i32 2
+; CHECK: {{%[0-9]+}} = OpInBoundsAccessChain [[ptr_A]] [[tmp]] [[uint_2]]
+
+  %7 = getelementptr %B, ptr %0, i32 0, i32 2, i32 1
+; CHECK: {{%[0-9]+}} = OpAccessChain [[ptr_uint]] [[tmp]] [[uint_2]] [[uint_1]]
+  %8 = getelementptr inbounds %B, ptr %0, i32 0, i32 2, i32 1
+; CHECK: {{%[0-9]+}} = OpInBoundsAccessChain [[ptr_uint]] [[tmp]] [[uint_2]] [[uint_1]]
+
+  %9 = getelementptr %B, ptr %0, i32 0, i32 2
+	%10 = getelementptr %A, ptr %9, i32 0, i32 1
+; CHECK: [[x:%[0-9]+]] = OpAccessChain [[ptr_A]] [[tmp]] [[uint_2]]
+; CHECK:   {{%[0-9]+}} = OpAccessChain [[ptr_uint]] [[x]] [[uint_1]]
+
+  ret void
+}
+
+attributes #1 = { "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" }

>From a9a0f7c97a6b850190465d19b268fa1d011dc3c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brioche at google.com>
Date: Thu, 21 Sep 2023 11:28:01 +0200
Subject: [PATCH 2/3] fixup! [SPIRV] Add OpAccessChain to instruction selector

fix superfluous tab
---
 llvm/test/CodeGen/SPIRV/logical-struct-access.ll | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/SPIRV/logical-struct-access.ll b/llvm/test/CodeGen/SPIRV/logical-struct-access.ll
index ba49b80ce5d1cbd..617aa70ccdb7e6c 100644
--- a/llvm/test/CodeGen/SPIRV/logical-struct-access.ll
+++ b/llvm/test/CodeGen/SPIRV/logical-struct-access.ll
@@ -49,7 +49,7 @@ entry:
 ; CHECK: {{%[0-9]+}} = OpInBoundsAccessChain [[ptr_uint]] [[tmp]] [[uint_2]] [[uint_1]]
 
   %9 = getelementptr %B, ptr %0, i32 0, i32 2
-	%10 = getelementptr %A, ptr %9, i32 0, i32 1
+  %10 = getelementptr %A, ptr %9, i32 0, i32 1
 ; CHECK: [[x:%[0-9]+]] = OpAccessChain [[ptr_A]] [[tmp]] [[uint_2]]
 ; CHECK:   {{%[0-9]+}} = OpAccessChain [[ptr_uint]] [[x]] [[uint_1]]
 

>From d39b7362648d8ffb094ef250755d762331c38c54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nathan=20Gau=C3=ABr?= <brioche at google.com>
Date: Tue, 26 Sep 2023 14:58:51 +0200
Subject: [PATCH 3/3] fixup! [SPIRV] Add OpAccessChain to instruction selector

fix trailing new line
---
 llvm/test/CodeGen/SPIRV/logical-access-chain.ll | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/test/CodeGen/SPIRV/logical-access-chain.ll b/llvm/test/CodeGen/SPIRV/logical-access-chain.ll
index 5fe60e8bbabb162..39f6d33712ef4c2 100644
--- a/llvm/test/CodeGen/SPIRV/logical-access-chain.ll
+++ b/llvm/test/CodeGen/SPIRV/logical-access-chain.ll
@@ -18,4 +18,3 @@ entry:
 }
 
 attributes #1 = { "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" }
-



More information about the llvm-commits mailing list