Skip to content

Commit 4023524

Browse files
vmaksimosys-ce-bb
authored andcommitted
Support OpPtrEqual, OpPtrNotEqual and OpPtrDiff to compare pointers (#2482)
This addresses p.2 and p.3 of #2460 Original commit: KhronosGroup/SPIRV-LLVM-Translator@4b4508438a6dfe5
1 parent c5f8977 commit 4023524

File tree

6 files changed

+155
-0
lines changed

6 files changed

+155
-0
lines changed

llvm-spirv/lib/SPIRV/SPIRVReader.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -2165,6 +2165,28 @@ Value *SPIRVToLLVM::transValueWithoutDecoration(SPIRVValue *BV, Function *F,
21652165
return mapValue(BV, V);
21662166
}
21672167

2168+
case OpPtrEqual:
2169+
case OpPtrNotEqual: {
2170+
auto *BC = static_cast<SPIRVBinary *>(BV);
2171+
auto Ops = transValue(BC->getOperands(), F, BB);
2172+
2173+
IRBuilder<> Builder(BB);
2174+
Value *Op1 = Builder.CreatePtrToInt(Ops[0], Type::getInt64Ty(*Context));
2175+
Value *Op2 = Builder.CreatePtrToInt(Ops[1], Type::getInt64Ty(*Context));
2176+
CmpInst::Predicate P =
2177+
OC == OpPtrEqual ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE;
2178+
Value *V = Builder.CreateICmp(P, Op1, Op2);
2179+
return mapValue(BV, V);
2180+
}
2181+
2182+
case OpPtrDiff: {
2183+
auto *BC = static_cast<SPIRVBinary *>(BV);
2184+
auto Ops = transValue(BC->getOperands(), F, BB);
2185+
IRBuilder<> Builder(BB);
2186+
Value *V = Builder.CreatePtrDiff(transType(BC->getType()), Ops[0], Ops[1]);
2187+
return mapValue(BV, V);
2188+
}
2189+
21682190
case OpCompositeConstruct: {
21692191
auto *CC = static_cast<SPIRVCompositeConstruct *>(BV);
21702192
auto Constituents = transValue(CC->getOperands(), F, BB);

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVInstruction.h

+14
Original file line numberDiff line numberDiff line change
@@ -669,10 +669,21 @@ class SPIRVBinary : public SPIRVInstTemplateBase {
669669
"Invalid type for bitwise instruction");
670670
assert((Op1Ty->getIntegerBitWidth() == Op2Ty->getIntegerBitWidth()) &&
671671
"Inconsistent BitWidth");
672+
} else if (isBinaryPtrOpCode(OpCode)) {
673+
assert((Op1Ty->isTypePointer() && Op2Ty->isTypePointer()) &&
674+
"Invalid types for PtrEqual, PtrNotEqual, or PtrDiff instruction");
675+
assert(static_cast<SPIRVTypePointer *>(Op1Ty)->getElementType() ==
676+
static_cast<SPIRVTypePointer *>(Op2Ty)->getElementType() &&
677+
"Invalid types for PtrEqual, PtrNotEqual, or PtrDiff instruction");
672678
} else {
673679
assert(0 && "Invalid op code!");
674680
}
675681
}
682+
VersionNumber getRequiredSPIRVVersion() const override {
683+
if (isBinaryPtrOpCode(OpCode))
684+
return VersionNumber::SPIRV_1_4;
685+
return VersionNumber::SPIRV_1_0;
686+
}
676687
};
677688

678689
template <Op OC>
@@ -707,6 +718,9 @@ _SPIRV_OP(BitwiseAnd)
707718
_SPIRV_OP(BitwiseOr)
708719
_SPIRV_OP(BitwiseXor)
709720
_SPIRV_OP(Dot)
721+
_SPIRV_OP(PtrEqual)
722+
_SPIRV_OP(PtrNotEqual)
723+
_SPIRV_OP(PtrDiff)
710724
#undef _SPIRV_OP
711725

712726
template <Op TheOpCode> class SPIRVInstNoOperand : public SPIRVInstruction {

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCode.h

+4
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ inline bool isBinaryOpCode(Op OpCode) {
7474
OpCode == OpDot || OpCode == OpIAddCarry || OpCode == OpISubBorrow;
7575
}
7676

77+
inline bool isBinaryPtrOpCode(Op OpCode) {
78+
return (unsigned)OpCode >= OpPtrEqual && (unsigned)OpCode <= OpPtrDiff;
79+
}
80+
7781
inline bool isShiftOpCode(Op OpCode) {
7882
return (unsigned)OpCode >= OpShiftRightLogical &&
7983
(unsigned)OpCode <= OpShiftLeftLogical;

llvm-spirv/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h

+3
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ _SPIRV_OP(GroupNonUniformBitwiseXor, 361)
329329
_SPIRV_OP(GroupNonUniformLogicalAnd, 362)
330330
_SPIRV_OP(GroupNonUniformLogicalOr, 363)
331331
_SPIRV_OP(GroupNonUniformLogicalXor, 364)
332+
_SPIRV_OP(PtrEqual, 401)
333+
_SPIRV_OP(PtrNotEqual, 402)
334+
_SPIRV_OP(PtrDiff, 403)
332335
_SPIRV_OP(CopyLogical, 400)
333336
_SPIRV_OP(GroupNonUniformRotateKHR, 4431)
334337
_SPIRV_OP(SDotKHR, 4450)
+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
; Check support of OpPtrDiff instruction that was added in SPIR-V 1.4
2+
3+
; RUN: llvm-as %s -o %t.bc
4+
; RUN: not llvm-spirv --spirv-max-version=1.3 %t.bc 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
5+
6+
; RUN: llvm-spirv %t.bc -o %t.spv
7+
; RUN: llvm-spirv %t.spv -to-text -o %t.spt
8+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
9+
; RUN: spirv-val %t.spv
10+
11+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
12+
; RUN: llvm-dis %t.rev.bc
13+
; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
14+
15+
; CHECK-ERROR: RequiresVersion: Cannot fulfill SPIR-V version restriction:
16+
; CHECK-ERROR-NEXT: SPIR-V version was restricted to at most 1.3 (66304) but a construct from the input requires SPIR-V version 1.4 (66560) or above
17+
18+
; SPIR-V 1.4
19+
; CHECK-SPIRV: 66560
20+
; CHECK-SPIRV: TypeInt [[#TypeInt:]] 32 0
21+
; CHECK-SPIRV: TypeFloat [[#TypeFloat:]] 32
22+
; CHECK-SPIRV: TypePointer [[#TypePointer:]] [[#]] [[#TypeFloat]]
23+
24+
; CHECK-SPIRV: Variable [[#TypePointer]] [[#Var:]]
25+
; CHECK-SPIRV: PtrDiff [[#TypeInt]] [[#]] [[#Var]] [[#Var]]
26+
27+
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
28+
target triple = "spir64-unknown-unknown"
29+
30+
; Function Attrs: nounwind
31+
define spir_kernel void @test(float %a) local_unnamed_addr #0 {
32+
entry:
33+
%0 = alloca float, align 4
34+
store float %a, ptr %0, align 4
35+
; CHECK-LLVM: %[[#Arg1:]] = ptrtoint ptr %[[#]] to i64
36+
; CHECK-LLVM: %[[#Arg2:]] = ptrtoint ptr %[[#]] to i64
37+
; CHECK-LLVM: %[[#Sub:]] = sub i64 %[[#Arg1]], %[[#Arg2]]
38+
; CHECK-LLVM: sdiv exact i64 %[[#Sub]], ptrtoint (ptr getelementptr (i32, ptr null, i32 1) to i64)
39+
%1 = call spir_func noundef i32 @_Z15__spirv_PtrDiff(ptr %0, ptr %0)
40+
ret void
41+
}
42+
43+
declare spir_func noundef i32 @_Z15__spirv_PtrDiff(ptr, ptr)
44+
45+
attributes #0 = { convergent nounwind writeonly }
46+
47+
!llvm.module.flags = !{!0}
48+
!opencl.ocl.version = !{!1}
49+
!opencl.spir.version = !{!1}
50+
51+
!0 = !{i32 1, !"wchar_size", i32 4}
52+
!1 = !{i32 2, i32 0}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
; Check support of OpPtrEqual and OpPtrNotEqual instructions that were added in SPIR-V 1.4
2+
3+
; RUN: llvm-as %s -o %t.bc
4+
; RUN: not llvm-spirv --spirv-max-version=1.3 %t.bc 2>&1 | FileCheck --check-prefix=CHECK-ERROR %s
5+
6+
; RUN: llvm-spirv %t.bc -o %t.spv
7+
; RUN: llvm-spirv %t.spv -to-text -o %t.spt
8+
; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
9+
; RUN: spirv-val %t.spv
10+
11+
; RUN: llvm-spirv -r %t.spv -o %t.rev.bc
12+
; RUN: llvm-dis %t.rev.bc
13+
; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
14+
15+
; CHECK-ERROR: RequiresVersion: Cannot fulfill SPIR-V version restriction:
16+
; CHECK-ERROR-NEXT: SPIR-V version was restricted to at most 1.3 (66304) but a construct from the input requires SPIR-V version 1.4 (66560) or above
17+
18+
; SPIR-V 1.4
19+
; CHECK-SPIRV: 66560
20+
; CHECK-SPIRV: TypeFloat [[#TypeFloat:]] 32
21+
; CHECK-SPIRV: TypePointer [[#TypePointer:]] [[#]] [[#TypeFloat]]
22+
; CHECK-SPIRV: TypeBool [[#TypeBool:]]
23+
24+
; CHECK-SPIRV: Variable [[#TypePointer]] [[#Var1:]]
25+
; CHECK-SPIRV: Variable [[#TypePointer]] [[#Var2:]]
26+
; CHECK-SPIRV: PtrEqual [[#TypeBool]] [[#]] [[#Var1]] [[#Var2]]
27+
; CHECK-SPIRV: PtrNotEqual [[#TypeBool]] [[#]] [[#Var1]] [[#Var2]]
28+
29+
target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
30+
target triple = "spir64-unknown-unknown"
31+
32+
; Function Attrs: nounwind
33+
define spir_kernel void @test(float %a, float %b) local_unnamed_addr #0 {
34+
entry:
35+
%0 = alloca float, align 4
36+
%1 = alloca float, align 4
37+
store float %a, ptr %0, align 4
38+
store float %b, ptr %1, align 4
39+
; CHECK-LLVM: %[[#Arg1:]] = ptrtoint ptr %[[#]] to i64
40+
; CHECK-LLVM: %[[#Arg2:]] = ptrtoint ptr %[[#]] to i64
41+
; CHECK-LLVM: icmp eq i64 %[[#Arg1]], %[[#Arg2]]
42+
%2 = call spir_func noundef i1 @_Z16__spirv_PtrEqual(ptr %0, ptr %1)
43+
; CHECK-LLVM: %[[#Arg3:]] = ptrtoint ptr %[[#]] to i64
44+
; CHECK-LLVM: %[[#Arg4:]] = ptrtoint ptr %[[#]] to i64
45+
; CHECK-LLVM: icmp ne i64 %[[#Arg3]], %[[#Arg4]]
46+
%3 = call spir_func noundef i1 @_Z19__spirv_PtrNotEqual(ptr %0, ptr %1)
47+
ret void
48+
}
49+
50+
declare spir_func noundef i1 @_Z16__spirv_PtrEqual(ptr, ptr)
51+
declare spir_func noundef i1 @_Z19__spirv_PtrNotEqual(ptr, ptr)
52+
53+
attributes #0 = { convergent nounwind writeonly }
54+
55+
!llvm.module.flags = !{!0}
56+
!opencl.ocl.version = !{!1}
57+
!opencl.spir.version = !{!1}
58+
59+
!0 = !{i32 1, !"wchar_size", i32 4}
60+
!1 = !{i32 2, i32 0}

0 commit comments

Comments
 (0)