[llvm] [SPIRV] Add OpAccessChain instruction support (PR #66253)
Nathan Gauër via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 21 02:28:26 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/2] [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/2] 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]]
More information about the llvm-commits
mailing list