Skip to content

Commit 59e5cb7

Browse files
[SPIR-V] Do not emit spv_ptrcast if GEP result is of expected type (#78122)
Prior to this change spv_ptrcast (and OpBitcast) was never emitted for GEP resulting pointers. While such SPIR-V was (mostly) accepted by the NEO GPU driver, the generated SPIR-V was incorrect. The newly added test (pointers/getelementptr-bitcast-load.ll) verifies that a correct bitcast is added for more complex cases and passes spirv-val. The test is based on an OpenCL CTS test (basic/prefetch).
1 parent 1b6c1a3 commit 59e5cb7

File tree

3 files changed

+45
-10
lines changed

3 files changed

+45
-10
lines changed

llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,9 @@ void SPIRVEmitIntrinsics::insertPtrCastInstr(Instruction *I) {
314314
if (A && A->getAllocatedType() == ExpectedElementType)
315315
return;
316316

317-
if (dyn_cast<GetElementPtrInst>(Pointer))
317+
// Do not emit spv_ptrcast if Pointer is a result of GEP of expected type.
318+
GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(Pointer);
319+
if (GEPI && GEPI->getResultElementType() == ExpectedElementType)
318320
return;
319321

320322
setInsertPointSkippingPhis(*IRB, I);

llvm/test/CodeGen/SPIRV/logical-struct-access.ll

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
; RUN: llc -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
22

3-
; CHECK: [[uint:%[0-9]+]] = OpTypeInt 32 0
3+
; CHECK-DAG: [[uint:%[0-9]+]] = OpTypeInt 32 0
44

55
%A = type {
66
i32,
77
i32
88
}
9-
; CHECK: [[A:%[0-9]+]] = OpTypeStruct [[uint]] [[uint]]
9+
; CHECK-DAG: [[A:%[0-9]+]] = OpTypeStruct [[uint]] [[uint]]
1010

1111
%B = type {
1212
%A,
1313
i32,
1414
%A
1515
}
16-
; CHECK: [[B:%[0-9]+]] = OpTypeStruct [[A]] [[uint]] [[A]]
16+
; CHECK-DAG: [[B:%[0-9]+]] = OpTypeStruct [[A]] [[uint]] [[A]]
1717

18-
; CHECK: [[uint_0:%[0-9]+]] = OpConstant [[uint]] 0
19-
; CHECK: [[uint_1:%[0-9]+]] = OpConstant [[uint]] 1
20-
; CHECK: [[uint_2:%[0-9]+]] = OpConstant [[uint]] 2
18+
; CHECK-DAG: [[uint_0:%[0-9]+]] = OpConstant [[uint]] 0
19+
; CHECK-DAG: [[uint_1:%[0-9]+]] = OpConstant [[uint]] 1
20+
; CHECK-DAG: [[uint_2:%[0-9]+]] = OpConstant [[uint]] 2
2121

22-
; CHECK: [[ptr_uint:%[0-9]+]] = OpTypePointer Function [[uint]]
23-
; CHECK: [[ptr_A:%[0-9]+]] = OpTypePointer Function [[A]]
24-
; CHECK: [[ptr_B:%[0-9]+]] = OpTypePointer Function [[B]]
22+
; CHECK-DAG: [[ptr_uint:%[0-9]+]] = OpTypePointer Function [[uint]]
23+
; CHECK-DAG: [[ptr_A:%[0-9]+]] = OpTypePointer Function [[A]]
24+
; CHECK-DAG: [[ptr_B:%[0-9]+]] = OpTypePointer Function [[B]]
2525

2626
define void @main() #1 {
2727
entry:
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
2+
; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
3+
4+
; CHECK-DAG: %[[#INT8:]] = OpTypeInt 8 0
5+
; CHECK-DAG: %[[#VEC3:]] = OpTypeVector %[[#INT8]] 3
6+
; CHECK-DAG: %[[#VEC4:]] = OpTypeVector %[[#INT8]] 4
7+
; CHECK-DAG: %[[#PTR_VEC3:]] = OpTypePointer CrossWorkgroup %[[#VEC3]]
8+
; CHECK-DAG: %[[#PTR_VEC4:]] = OpTypePointer CrossWorkgroup %[[#VEC4]]
9+
10+
; CHECK: %[[#AC1:]] = OpInBoundsPtrAccessChain %[[#PTR_VEC3]] %[[#]] %[[#]]
11+
; CHECK: %[[#BC1:]] = OpBitcast %[[#PTR_VEC4]] %[[#AC1]]
12+
; CHECK: %[[#LD1:]] = OpLoad %[[#VEC4]] %[[#BC1]] Aligned 4
13+
; CHECK: OpReturn
14+
15+
define spir_kernel void @foo(ptr addrspace(1) %a, i64 %b) {
16+
%index = getelementptr inbounds <3 x i8>, ptr addrspace(1) %a, i64 %b
17+
%loadv = load <4 x i8>, ptr addrspace(1) %index, align 4
18+
ret void
19+
}
20+
21+
; CHECK: %[[#AC2:]] = OpInBoundsPtrAccessChain %[[#PTR_VEC3]] %[[#]] %[[#]]
22+
; CHECK: %[[#BC2:]] = OpBitcast %[[#PTR_VEC4]] %[[#AC2]]
23+
; CHECK: %[[#LD2:]] = OpLoad %[[#VEC4]] %[[#BC2]] Aligned 4
24+
; CHECK: OpReturn
25+
26+
define spir_kernel void @bar(ptr addrspace(1) %a, i64 %b) {
27+
%index = getelementptr inbounds <3 x i8>, ptr addrspace(1) %a, i64 %b
28+
; This redundant bitcast is left here itentionally to simulate the conversion
29+
; from older LLVM IR with typed pointers.
30+
%cast = bitcast ptr addrspace(1) %index to ptr addrspace(1)
31+
%loadv = load <4 x i8>, ptr addrspace(1) %cast, align 4
32+
ret void
33+
}

0 commit comments

Comments
 (0)