Skip to content

Commit 0161b32

Browse files
authored
Fix production of OpPtrCastToGeneric instruction (#1163)
In LLVM it is valid if addrspace cast result pointer has not only other address space, but also other element type. However spec states that for Storage Class changing instructions Result Type and Pointer must point to the same type. So, this patch adds a regularization step that adds an additional bitcast in case address space cast changes pointer element type as well and then everything can be easily translated to valid SPIR-V that is accepted by spirv-val.
1 parent d38569f commit 0161b32

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

lib/SPIRV/SPIRVRegularizeLLVM.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,25 @@ bool SPIRVRegularizeLLVMBase::regularize() {
351351
II.setMetadata(MDName, nullptr);
352352
}
353353
}
354+
// Add an additional bitcast in case address space cast also changes
355+
// pointer element type.
356+
if (auto *ASCast = dyn_cast<AddrSpaceCastInst>(&II)) {
357+
Type *DestTy = ASCast->getDestTy();
358+
Type *SrcTy = ASCast->getSrcTy();
359+
if (DestTy->getPointerElementType() !=
360+
SrcTy->getPointerElementType()) {
361+
PointerType *InterTy =
362+
PointerType::get(DestTy->getPointerElementType(),
363+
SrcTy->getPointerAddressSpace());
364+
BitCastInst *NewBCast = new BitCastInst(
365+
ASCast->getPointerOperand(), InterTy, /*NameStr=*/"", ASCast);
366+
AddrSpaceCastInst *NewASCast =
367+
new AddrSpaceCastInst(NewBCast, DestTy, /*NameStr=*/"", ASCast);
368+
ToErase.push_back(ASCast);
369+
ASCast->dropAllReferences();
370+
ASCast->replaceAllUsesWith(NewASCast);
371+
}
372+
}
354373
if (auto Cmpxchg = dyn_cast<AtomicCmpXchgInst>(&II)) {
355374
// Transform:
356375
// %1 = cmpxchg i32* %ptr, i32 %comparator, i32 %0 seq_cst acquire

test/transcoding/enqueue_kernel.cl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// RUN: llvm-spirv %t.bc -spirv-text -o %t.spv.txt
33
// RUN: FileCheck < %t.spv.txt %s --check-prefix=CHECK-SPIRV
44
// RUN: llvm-spirv %t.bc -o %t.spv
5+
// RUN: spirv-val %t.spv
56
// RUN: llvm-spirv -r %t.spv -o %t.rev.bc
67
// RUN: llvm-dis %t.rev.bc
78
// RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
@@ -60,7 +61,8 @@ kernel void device_side_enqueue(global int *a, global int *b, int i, char c0) {
6061
// [[BlockKer1]] [[BlockLit1]] [[ConstInt17]] [[ConstInt8]]
6162

6263
// CHECK-LLVM: [[Block2:%[0-9]+]] = bitcast [[BlockTy2]]* %block to %struct.__opencl_block_literal_generic*
63-
// CHECK-LLVM: [[Block2Ptr:%[0-9]+]] = addrspacecast %struct.__opencl_block_literal_generic* [[Block2]] to i8 addrspace(4)*
64+
// CHECK-LLVM: [[InterCast2:%[0-9]+]] = bitcast %struct.__opencl_block_literal_generic* [[Block2]] to i8
65+
// CHECK-LLVM: [[Block2Ptr:%[0-9]+]] = addrspacecast i8* [[InterCast2]] to i8 addrspace(4)*
6466
// CHECK-LLVM: [[BlockInv2:%[0-9]+]] = addrspacecast void (i8 addrspace(4)*)* @__device_side_enqueue_block_invoke_kernel to i8 addrspace(4)*
6567
// CHECK-LLVM: call i32 @__enqueue_kernel_basic(%opencl.queue_t* {{.*}}, i32 {{.*}}, %struct.ndrange_t* {{.*}}, i8 addrspace(4)* [[BlockInv2]], i8 addrspace(4)* [[Block2Ptr]])
6668
enqueue_kernel(default_queue, flags, ndrange,
@@ -79,7 +81,8 @@ kernel void device_side_enqueue(global int *a, global int *b, int i, char c0) {
7981
// [[BlockKer2]] [[BlockLit2]] [[ConstInt20]] [[ConstInt8]]
8082

8183
// CHECK-LLVM: [[Block3:%[0-9]+]] = bitcast [[BlockTy3]]* %block4 to %struct.__opencl_block_literal_generic*
82-
// CHECK-LLVM: [[Block3Ptr:%[0-9]+]] = addrspacecast %struct.__opencl_block_literal_generic* [[Block3]] to i8 addrspace(4)
84+
// CHECK-LLVM: [[InterCast3:%[0-9]+]] = bitcast %struct.__opencl_block_literal_generic* [[Block3]] to i8
85+
// CHECK-LLVM: [[Block3Ptr:%[0-9]+]] = addrspacecast i8* [[InterCast3]] to i8 addrspace(4)
8386
// CHECK-LLVM: [[BlockInv3:%[0-9]+]] = addrspacecast void (i8 addrspace(4)*)* @__device_side_enqueue_block_invoke_2_kernel to i8 addrspace(4)*
8487
// CHECK-LLVM: call i32 @__enqueue_kernel_basic_events(%opencl.queue_t* {{.*}}, i32 {{.*}}, %struct.ndrange_t* {{.*}}, i32 2, %opencl.clk_event_t* addrspace(4)* {{.*}}, %opencl.clk_event_t* addrspace(4)* {{.*}}, i8 addrspace(4)* [[BlockInv3]], i8 addrspace(4)* [[Block3Ptr]])
8588
enqueue_kernel(default_queue, flags, ndrange, 2, &event_wait_list, &clk_event,
@@ -140,7 +143,8 @@ kernel void device_side_enqueue(global int *a, global int *b, int i, char c0) {
140143
// [[BlockKer5]] [[BlockLit5]] [[ConstInt20]] [[ConstInt8]]
141144

142145
// CHECK-LLVM: [[Block5:%[0-9]+]] = bitcast [[BlockTy3]]* %block15 to %struct.__opencl_block_literal_generic*
143-
// CHECK-LLVM: [[Block5Ptr:%[0-9]+]] = addrspacecast %struct.__opencl_block_literal_generic* [[Block5]] to i8 addrspace(4)
146+
// CHECK-LLVM: [[InterCast5:%[0-9]+]] = bitcast %struct.__opencl_block_literal_generic* [[Block5]] to i8
147+
// CHECK-LLVM: [[Block5Ptr:%[0-9]+]] = addrspacecast i8* [[InterCast5]] to i8 addrspace(4)
144148
// CHECK-LLVM: [[BlockInv5:%[0-9]+]] = addrspacecast void (i8 addrspace(4)*)* @__device_side_enqueue_block_invoke_5_kernel to i8 addrspace(4)*
145149
// CHECK-LLVM: call i32 @__enqueue_kernel_basic_events(%opencl.queue_t* {{.*}}, i32 {{.*}}, %struct.ndrange_t* {{.*}}, i32 0, %opencl.clk_event_t* addrspace(4)* null, %opencl.clk_event_t* addrspace(4)* {{.*}}, i8 addrspace(4)* [[BlockInv5]], i8 addrspace(4)* [[Block5Ptr]])
146150
enqueue_kernel(default_queue, flags, ndrange, 0, NULL, &clk_event,

0 commit comments

Comments
 (0)