Skip to content

Commit 4b2a35b

Browse files
bashbaugjsji
authored andcommitted
handle OpBitcast between pointers and non-pointers (#2948)
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). Original commit: KhronosGroup/SPIRV-LLVM-Translator@aafca810e5cd645
1 parent 26afacd commit 4b2a35b

File tree

3 files changed

+99
-0
lines changed

3 files changed

+99
-0
lines changed

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,6 +1087,41 @@ Value *SPIRVToLLVM::transConvertInst(SPIRVValue *BV, Function *F,
10871087
case OpFConvert:
10881088
CO = IsExt ? Instruction::FPExt : Instruction::FPTrunc;
10891089
break;
1090+
case OpBitcast:
1091+
// OpBitcast need to be handled as a special-case when the source is a
1092+
// pointer and the destination is not a pointer, and where the source is not
1093+
// a pointer and the destination is a pointer. This is supported by the
1094+
// SPIR-V bitcast, but not by the LLVM bitcast.
1095+
CO = Instruction::BitCast;
1096+
if (Src->getType()->isPointerTy() && !Dst->isPointerTy()) {
1097+
if (auto *DstVecTy = dyn_cast<FixedVectorType>(Dst)) {
1098+
unsigned TotalBitWidth =
1099+
DstVecTy->getElementType()->getIntegerBitWidth() *
1100+
DstVecTy->getNumElements();
1101+
auto *IntTy = Type::getIntNTy(BB->getContext(), TotalBitWidth);
1102+
if (BB) {
1103+
Src = CastInst::CreatePointerCast(Src, IntTy, "", BB);
1104+
} else {
1105+
Src = ConstantExpr::getPointerCast(dyn_cast<Constant>(Src), IntTy);
1106+
}
1107+
} else {
1108+
CO = Instruction::PtrToInt;
1109+
}
1110+
} else if (!Src->getType()->isPointerTy() && Dst->isPointerTy()) {
1111+
if (auto *SrcVecTy = dyn_cast<FixedVectorType>(Src->getType())) {
1112+
unsigned TotalBitWidth =
1113+
SrcVecTy->getElementType()->getIntegerBitWidth() *
1114+
SrcVecTy->getNumElements();
1115+
auto *IntTy = Type::getIntNTy(BB->getContext(), TotalBitWidth);
1116+
if (BB) {
1117+
Src = CastInst::Create(Instruction::BitCast, Src, IntTy, "", BB);
1118+
} else {
1119+
Src = ConstantExpr::getBitCast(dyn_cast<Constant>(Src), IntTy);
1120+
}
1121+
}
1122+
CO = Instruction::IntToPtr;
1123+
}
1124+
break;
10901125
default:
10911126
CO = static_cast<CastInst::CastOps>(OpCodeMap::rmap(BC->getOpCode()));
10921127
}
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 -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
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 -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)