Skip to content

Commit

Permalink
Fix translation of relational operations (#476)
Browse files Browse the repository at this point in the history
Whereas it is not possible to generate vector of bools in FE,
we have to change return type for corresponding instructions in SPIRV
translator to vector of bools. SPIRV translator already did this for
some instructions, this patch extends this behaviour to handle more
instructions.
  • Loading branch information
Fznamznon authored Mar 27, 2020
1 parent 8114d7f commit cb3be86
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 6 deletions.
19 changes: 13 additions & 6 deletions lib/SPIRV/SPIRVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2448,24 +2448,31 @@ LLVMToSPIRV::transBuiltinToInstWithoutDecoration(Op OC, CallInst *CI,
if (isCvtOpCode(OC) && OC != OpGenericCastToPtrExplicit) {
return BM->addUnaryInst(OC, transType(CI->getType()),
transValue(CI->getArgOperand(0), BB), BB);
} else if (isCmpOpCode(OC)) {
assert(CI && CI->getNumArgOperands() == 2 && "Invalid call inst");
} else if (isCmpOpCode(OC) || isUnaryPredicateOpCode(OC)) {
auto ResultTy = CI->getType();
Type *BoolTy = IntegerType::getInt1Ty(M->getContext());
auto IsVector = ResultTy->isVectorTy();
if (IsVector)
BoolTy = VectorType::get(BoolTy, ResultTy->getVectorNumElements());
auto BBT = transType(BoolTy);
auto Cmp = BM->addCmpInst(OC, BBT, transValue(CI->getArgOperand(0), BB),
transValue(CI->getArgOperand(1), BB), BB);
SPIRVInstruction *Res;
if (isCmpOpCode(OC)) {
assert(CI && CI->getNumArgOperands() == 2 && "Invalid call inst");
Res = BM->addCmpInst(OC, BBT, transValue(CI->getArgOperand(0), BB),
transValue(CI->getArgOperand(1), BB), BB);
} else {
assert(CI && CI->getNumArgOperands() == 1 && "Invalid call inst");
Res =
BM->addUnaryInst(OC, BBT, transValue(CI->getArgOperand(0), BB), BB);
}
// OpenCL C and OpenCL C++ built-ins may have different return type
if (ResultTy == BoolTy)
return Cmp;
return Res;
assert(IsVector || (!IsVector && ResultTy->isIntegerTy(32)));
auto Zero = transValue(Constant::getNullValue(ResultTy), BB);
auto One = transValue(
IsVector ? Constant::getAllOnesValue(ResultTy) : getInt32(M, 1), BB);
return BM->addSelectInst(Cmp, One, Zero, BB);
return BM->addSelectInst(Res, One, Zero, BB);
} else if (isBinaryOpCode(OC)) {
assert(CI && CI->getNumArgOperands() == 2 && "Invalid call inst");
return BM->addBinaryInst(OC, transType(CI->getType()),
Expand Down
4 changes: 4 additions & 0 deletions lib/SPIRV/libSPIRV/SPIRVOpCode.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ inline bool isLogicalOpCode(Op OpCode) {
return (unsigned)OpCode >= OpLogicalEqual && (unsigned)OpCode <= OpLogicalNot;
}

inline bool isUnaryPredicateOpCode(Op OpCode) {
return (unsigned)OpCode >= OpAny && (unsigned)OpCode <= OpSignBitSet;
}

inline bool isBitwiseOpCode(Op OpCode) {
return (unsigned)OpCode >= OpBitwiseOr && (unsigned)OpCode <= OpBitwiseAnd;
}
Expand Down
57 changes: 57 additions & 0 deletions test/relationals.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
; RUN: llvm-as %s -o %t.bc
; RUN: llvm-spirv %t.bc -spirv-text -o - | FileCheck %s --check-prefix=CHECK-SPIRV
; RUN: llvm-spirv %t.bc -o %t.spv
; RUN: spirv-val %t.spv

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"
target triple = "spir"

declare dso_local spir_func <4 x i8> @_Z13__spirv_IsNanIDv4_aDv4_fET_T0_(<4 x float>)
declare dso_local spir_func <4 x i8> @_Z13__spirv_IsInfIDv4_aDv4_fET_T0_(<4 x float>)
declare dso_local spir_func <4 x i8> @_Z16__spirv_IsFiniteIDv4_aDv4_fET_T0_(<4 x float>)
declare dso_local spir_func <4 x i8> @_Z16__spirv_IsNormalIDv4_aDv4_fET_T0_(<4 x float>)
declare dso_local spir_func <4 x i8> @_Z18__spirv_SignBitSetIDv4_aDv4_fET_T0_(<4 x float>)

; CHECK-SPIRV: {{[0-9]+}} TypeBool [[TBool:[0-9]+]]
; CHECK-SPIRV: {{[0-9]+}} TypeVector [[TBoolVec:[0-9]+]] [[TBool]]

; Function Attrs: nounwind readnone
define spir_kernel void @k() #0 !kernel_arg_addr_space !0 !kernel_arg_access_qual !0 !kernel_arg_type !0 !kernel_arg_base_type !0 !kernel_arg_type_qual !0 {
entry:
%arg1 = alloca <4 x float>, align 16
%ret = alloca <4 x i8>, align 4
%0 = load <4 x float>, <4 x float>* %arg1, align 16
%call1 = call spir_func <4 x i8> @_Z13__spirv_IsNanIDv4_aDv4_fET_T0_(<4 x float> %0)
; CHECK-SPIRV: {{[0-9]+}} IsNan [[TBoolVec]] [[IsNanRes:[0-9]+]]
; CHECK-SPIRV: {{[0-9]+}} Select {{[0-9]+}} [[SelectRes:[0-9]+]] [[IsNanRes]]
; CHECK-SPIRV: {{[0-9]+}} Store {{[0-9]+}} [[SelectRes]]
store <4 x i8> %call1, <4 x i8>* %ret, align 4
%call2 = call spir_func <4 x i8> @_Z13__spirv_IsInfIDv4_aDv4_fET_T0_(<4 x float> %0)
; CHECK-SPIRV: {{[0-9]+}} IsInf [[TBoolVec]] [[IsInfRes:[0-9]+]]
; CHECK-SPIRV: {{[0-9]+}} Select {{[0-9]+}} [[Select1Res:[0-9]+]] [[IsInfRes]]
; CHECK-SPIRV: {{[0-9]+}} Store {{[0-9]+}} [[Select1Res]]
store <4 x i8> %call2, <4 x i8>* %ret, align 4
%call3 = call spir_func <4 x i8> @_Z16__spirv_IsFiniteIDv4_aDv4_fET_T0_(<4 x float> %0)
; CHECK-SPIRV: {{[0-9]+}} IsFinite [[TBoolVec]] [[IsFiniteRes:[0-9]+]]
; CHECK-SPIRV: {{[0-9]+}} Select {{[0-9]+}} [[Select2Res:[0-9]+]] [[IsFiniteRes]]
; CHECK-SPIRV: {{[0-9]+}} Store {{[0-9]+}} [[Select2Res]]
store <4 x i8> %call3, <4 x i8>* %ret, align 4
%call4 = call spir_func <4 x i8> @_Z16__spirv_IsNormalIDv4_aDv4_fET_T0_(<4 x float> %0)
; CHECK-SPIRV: {{[0-9]+}} IsNormal [[TBoolVec]] [[IsNormalRes:[0-9]+]]
; CHECK-SPIRV: {{[0-9]+}} Select {{[0-9]+}} [[Select3Res:[0-9]+]] [[IsNormalRes]]
; CHECK-SPIRV: {{[0-9]+}} Store {{[0-9]+}} [[Select3Res]]
store <4 x i8> %call4, <4 x i8>* %ret, align 4
%call5 = call spir_func <4 x i8> @_Z18__spirv_SignBitSetIDv4_aDv4_fET_T0_(<4 x float> %0)
; CHECK-SPIRV: {{[0-9]+}} SignBitSet [[TBoolVec]] [[SignBitSetRes:[0-9]+]]
; CHECK-SPIRV: {{[0-9]+}} Select {{[0-9]+}} [[Select4Res:[0-9]+]] [[SignBitSetRes]]
; CHECK-SPIRV: {{[0-9]+}} Store {{[0-9]+}} [[Select4Res]]
store <4 x i8> %call5, <4 x i8>* %ret, align 4
ret void
}

!llvm.module.flags = !{!1}
!opencl.spir.version = !{!2}

!0 = !{}
!1 = !{i32 1, !"wchar_size", i32 4}
!2 = !{i32 1, i32 2}

0 comments on commit cb3be86

Please sign in to comment.