Skip to content

Commit 62c9e88

Browse files
svenvhbashbaug
andauthored
[Backport to 15] handle OpBitcast between pointers and non-pointers (#2948) (#2955)
Adds support for SPIR-V OpBitcast instructions where the source is a pointer and the destination is not a pointer, and where the source is not a pointer and the destination is a pointer. This needs to be handled as a special case because the LLVM bitcast instruction does not support this. Handles bitcasts between pointers and scalar integers, which is supported by all SPIR-V versions, and pointers and vectors of integers, which is supported by SPIR-V 1.5 (though only for vectors of 32-bit integers). (cherry picked from commit aafca81) Co-authored-by: Ben Ashbaugh <ben.ashbaugh@intel.com>
1 parent dacd7d0 commit 62c9e88

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

lib/SPIRV/SPIRVReader.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,41 @@ Value *SPIRVToLLVM::transConvertInst(SPIRVValue *BV, Function *F,
11741174
case OpFConvert:
11751175
CO = IsExt ? Instruction::FPExt : Instruction::FPTrunc;
11761176
break;
1177+
case OpBitcast:
1178+
// OpBitcast need to be handled as a special-case when the source is a
1179+
// pointer and the destination is not a pointer, and where the source is not
1180+
// a pointer and the destination is a pointer. This is supported by the
1181+
// SPIR-V bitcast, but not by the LLVM bitcast.
1182+
CO = Instruction::BitCast;
1183+
if (Src->getType()->isPointerTy() && !Dst->isPointerTy()) {
1184+
if (auto *DstVecTy = dyn_cast<FixedVectorType>(Dst)) {
1185+
unsigned TotalBitWidth =
1186+
DstVecTy->getElementType()->getIntegerBitWidth() *
1187+
DstVecTy->getNumElements();
1188+
auto *IntTy = Type::getIntNTy(BB->getContext(), TotalBitWidth);
1189+
if (BB) {
1190+
Src = CastInst::CreatePointerCast(Src, IntTy, "", BB);
1191+
} else {
1192+
Src = ConstantExpr::getPointerCast(dyn_cast<Constant>(Src), IntTy);
1193+
}
1194+
} else {
1195+
CO = Instruction::PtrToInt;
1196+
}
1197+
} else if (!Src->getType()->isPointerTy() && Dst->isPointerTy()) {
1198+
if (auto *SrcVecTy = dyn_cast<FixedVectorType>(Src->getType())) {
1199+
unsigned TotalBitWidth =
1200+
SrcVecTy->getElementType()->getIntegerBitWidth() *
1201+
SrcVecTy->getNumElements();
1202+
auto *IntTy = Type::getIntNTy(BB->getContext(), TotalBitWidth);
1203+
if (BB) {
1204+
Src = CastInst::Create(Instruction::BitCast, Src, IntTy, "", BB);
1205+
} else {
1206+
Src = ConstantExpr::getBitCast(dyn_cast<Constant>(Src), IntTy);
1207+
}
1208+
}
1209+
CO = Instruction::IntToPtr;
1210+
}
1211+
break;
11771212
default:
11781213
CO = static_cast<CastInst::CastOps>(OpCodeMap::rmap(BC->getOpCode()));
11791214
}

test/OpBitcast_ptr_scalar.spvasm

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
; Check support of OpBitcast with pointer operands
2+
; Converts to scalar integers, which is supported by all SPIR-V versions
3+
4+
; REQUIRES: spirv-as
5+
; RUN: spirv-as --target-env spv1.0 -o %t.spv %s
6+
; RUN: spirv-val %t.spv
7+
; RUN: llvm-spirv -emit-opaque-pointers -r %t.spv -o %t.rev.bc
8+
; RUN: llvm-dis %t.rev.bc
9+
; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
10+
OpCapability Addresses
11+
OpCapability Kernel
12+
OpCapability Int64
13+
OpMemoryModel Physical64 OpenCL
14+
OpEntryPoint Kernel %kernel "test"
15+
%uint = OpTypeInt 32 0
16+
%ulong = OpTypeInt 64 0
17+
%void = OpTypeVoid
18+
%pptr_int = OpTypePointer Function %uint
19+
%kernel_sig = OpTypeFunction %void
20+
%kernel = OpFunction %void None %kernel_sig
21+
%entry = OpLabel
22+
%srcptr = OpVariable %pptr_int Function
23+
%dstint = OpBitcast %ulong %srcptr
24+
%dstptr = OpBitcast %pptr_int %dstint
25+
OpReturn
26+
OpFunctionEnd
27+
28+
29+
; CHECK-LLVM: [[SRCPTR:%[a-z0-9.]+]] = alloca i32, align 4
30+
; CHECK-LLVM: [[DSTINT:%[a-z0-9.]+]] = ptrtoint ptr [[SRCPTR]] to i64
31+
; CHECK-LLVM: [[DSTPTR:%[a-z0-9.]+]] = inttoptr i64 [[DSTINT]] to ptr

test/OpBitcast_ptr_vector.spvasm

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; Check support of OpBitcast with pointer operands
2+
; Converts to vectors of integers, which is supported by SPIR-V 1.5
3+
4+
; REQUIRES: spirv-as
5+
; RUN: spirv-as --target-env spv1.5 -o %t.spv %s
6+
; RUN: spirv-val %t.spv
7+
; RUN: llvm-spirv -emit-opaque-pointers -r %t.spv -o %t.rev.bc
8+
; RUN: llvm-dis %t.rev.bc
9+
; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
10+
OpCapability Addresses
11+
OpCapability Kernel
12+
OpCapability Int64
13+
OpMemoryModel Physical64 OpenCL
14+
OpEntryPoint Kernel %kernel "test"
15+
%uint = OpTypeInt 32 0
16+
%uint2 = OpTypeVector %uint 2
17+
%void = OpTypeVoid
18+
%pptr_int = OpTypePointer Function %uint
19+
%kernel_sig = OpTypeFunction %void
20+
%kernel = OpFunction %void None %kernel_sig
21+
%entry = OpLabel
22+
%srcptr = OpVariable %pptr_int Function
23+
%dstint2 = OpBitcast %uint2 %srcptr
24+
%dstptr = OpBitcast %pptr_int %dstint2
25+
OpReturn
26+
OpFunctionEnd
27+
28+
29+
; CHECK-LLVM: [[SRCPTR:%[a-z0-9.]+]] = alloca i32, align 4
30+
; CHECK-LLVM: [[TMPLONG0:%[a-z0-9.]+]] = ptrtoint ptr [[SRCPTR]] to i64
31+
; CHECK-LLVM: [[DSTINT2:%[a-z0-9.]+]] = bitcast i64 [[TMPLONG0]] to <2 x i32>
32+
; CHECK-LLVM: [[TMPLONG1:%[a-z0-9.]+]] = bitcast <2 x i32> [[DSTINT2]] to i64
33+
; CHECK-LLVM: [[DSTPTR:%[a-z0-9.]+]] = inttoptr i64 [[TMPLONG1]] to ptr

0 commit comments

Comments
 (0)