Skip to content

Commit 43c197b

Browse files
svenvhbashbaug
andauthored
[Backport to 14] handle OpBitcast between pointers and non-pointers (#2948) (#2952)
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 <[email protected]>
1 parent e27104f commit 43c197b

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
@@ -1070,6 +1070,41 @@ Value *SPIRVToLLVM::transConvertInst(SPIRVValue *BV, Function *F,
10701070
case OpFConvert:
10711071
CO = IsExt ? Instruction::FPExt : Instruction::FPTrunc;
10721072
break;
1073+
case OpBitcast:
1074+
// OpBitcast need to be handled as a special-case when the source is a
1075+
// pointer and the destination is not a pointer, and where the source is not
1076+
// a pointer and the destination is a pointer. This is supported by the
1077+
// SPIR-V bitcast, but not by the LLVM bitcast.
1078+
CO = Instruction::BitCast;
1079+
if (Src->getType()->isPointerTy() && !Dst->isPointerTy()) {
1080+
if (auto *DstVecTy = dyn_cast<FixedVectorType>(Dst)) {
1081+
unsigned TotalBitWidth =
1082+
DstVecTy->getElementType()->getIntegerBitWidth() *
1083+
DstVecTy->getNumElements();
1084+
auto *IntTy = Type::getIntNTy(BB->getContext(), TotalBitWidth);
1085+
if (BB) {
1086+
Src = CastInst::CreatePointerCast(Src, IntTy, "", BB);
1087+
} else {
1088+
Src = ConstantExpr::getPointerCast(dyn_cast<Constant>(Src), IntTy);
1089+
}
1090+
} else {
1091+
CO = Instruction::PtrToInt;
1092+
}
1093+
} else if (!Src->getType()->isPointerTy() && Dst->isPointerTy()) {
1094+
if (auto *SrcVecTy = dyn_cast<FixedVectorType>(Src->getType())) {
1095+
unsigned TotalBitWidth =
1096+
SrcVecTy->getElementType()->getIntegerBitWidth() *
1097+
SrcVecTy->getNumElements();
1098+
auto *IntTy = Type::getIntNTy(BB->getContext(), TotalBitWidth);
1099+
if (BB) {
1100+
Src = CastInst::Create(Instruction::BitCast, Src, IntTy, "", BB);
1101+
} else {
1102+
Src = ConstantExpr::getBitCast(dyn_cast<Constant>(Src), IntTy);
1103+
}
1104+
}
1105+
CO = Instruction::IntToPtr;
1106+
}
1107+
break;
10731108
default:
10741109
CO = static_cast<CastInst::CastOps>(OpCodeMap::rmap(BC->getOpCode()));
10751110
}

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 -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 i32* [[SRCPTR]] to i64
31+
; CHECK-LLVM: [[DSTPTR:%[a-z0-9.]+]] = inttoptr i64 [[DSTINT]] to i32*

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 -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 i32* [[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 i32*

0 commit comments

Comments
 (0)