Skip to content

Commit

Permalink
Fix codegen for logical operations on bool vectors (google#210)
Browse files Browse the repository at this point in the history
Bitwise instructions were being emitted. The tests added
only cover And and Or as I couldn't find a way of
producing Xor on boolean vectors which seems to line up
with a few observations from the OpenCL specification:

- there is no xor logical operator (although ^^ has been
  reserved for that use)
- boolean vectors aren't explicitly specified (even
  though booln (2,3,4,8 and 16) is a reserved type)
- the result of relational operators applied to two
  vectors is guaranteed to be a vector of signed integers
  (this is the case that made me discover the issue)

Clang's omission of the sign extension to int vectors
when the result of multiple relational operators is
only used by a logical operation is an optimisation.
Since there is no logical xor operator it is
reasonable for Clang to always sign extend the result
of relational operators (according to §6.3d of the
OpenCL 1.2 specification) that feed into an xor
operator and perform the operation as bitwise.

An optimisation similar to that done for And and Or
could be made by clspv in cases where the results of
relational operators are only used by xor operators
but should IMHO be discussed separately from this
change.

Also tidy up a few related things:

- use isIntOrIntVectorTy(1) where it makes the code clearer
- tighten the check in SPIRVProducerPass::GenerateInstruction
  that special cases Instruction::Xor for booleans. It was
  allowing OpLogicalNot to be emitted in all cases where one
  of the operands was constant, which is correct only when the
  constrant is 1. The value of the constant is now checked.

Signed-off-by: Kévin Petit <[email protected]>
  • Loading branch information
kpet authored and alan-baker committed Oct 18, 2018
1 parent a353c83 commit 24272b6
Show file tree
Hide file tree
Showing 3 changed files with 174 additions and 11 deletions.
19 changes: 8 additions & 11 deletions lib/SPIRVProducerPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -793,9 +793,7 @@ void SPIRVProducerPass::GenerateLLVMIRInfo(Module &M, const DataLayout &DL) {

auto OpTy = I.getOperand(0)->getType();

if (OpTy->isIntegerTy(1) ||
(OpTy->isVectorTy() &&
OpTy->getVectorElementType()->isIntegerTy(1))) {
if (OpTy->isIntOrIntVectorTy(1)) {
if (I.getOpcode() == Instruction::ZExt) {
APInt One(32, 1);
FindConstant(Constant::getNullValue(I.getType()));
Expand Down Expand Up @@ -866,9 +864,7 @@ void SPIRVProducerPass::GenerateLLVMIRInfo(Module &M, const DataLayout &DL) {

auto OpTy = I.getOperand(0)->getType();

if (OpTy->isIntegerTy(1) ||
(OpTy->isVectorTy() &&
OpTy->getVectorElementType()->isIntegerTy(1))) {
if (OpTy->isIntOrIntVectorTy(1)) {
if (I.getOpcode() == Instruction::ZExt) {
APInt One(32, 1);
FindConstant(Constant::getNullValue(I.getType()));
Expand Down Expand Up @@ -3480,7 +3476,7 @@ spv::Op SPIRVProducerPass::GetSPIRVCastOpcode(Instruction &I) {
}

spv::Op SPIRVProducerPass::GetSPIRVBinaryOpcode(Instruction &I) {
if (I.getType()->isIntegerTy(1)) {
if (I.getType()->isIntOrIntVectorTy(1)) {
switch (I.getOpcode()) {
default:
break;
Expand Down Expand Up @@ -3545,9 +3541,7 @@ void SPIRVProducerPass::GenerateInstruction(Instruction &I) {
if ((I.getOpcode() == Instruction::ZExt ||
I.getOpcode() == Instruction::SExt ||
I.getOpcode() == Instruction::UIToFP) &&
(OpTy->isIntegerTy(1) ||
(OpTy->isVectorTy() &&
OpTy->getVectorElementType()->isIntegerTy(1)))) {
OpTy->isIntOrIntVectorTy(1)) {
//
// Generate OpSelect.
//
Expand Down Expand Up @@ -3623,7 +3617,10 @@ void SPIRVProducerPass::GenerateInstruction(Instruction &I) {
// Handle xor with i1 type specially.
if (I.getOpcode() == Instruction::Xor &&
I.getType() == Type::getInt1Ty(Context) &&
(isa<Constant>(I.getOperand(0)) || isa<Constant>(I.getOperand(1)))) {
((isa<ConstantInt>(I.getOperand(0)) &&
!cast<ConstantInt>(I.getOperand(0))->isZero()) ||
(isa<ConstantInt>(I.getOperand(1)) &&
!cast<ConstantInt>(I.getOperand(1))->isZero()))) {
//
// Generate OpLogicalNot.
//
Expand Down
83 changes: 83 additions & 0 deletions test/bool_vector_and.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// RUN: clspv %s -S -o %t.spvasm
// RUN: FileCheck %s < %t.spvasm
// RUN: clspv %s -o %t.spv
// RUN: spirv-dis -o %t2.spvasm %t.spv
// RUN: FileCheck %s < %t2.spvasm
// RUN: spirv-val --target-env vulkan1.0 %t.spv

// CHECK: ; SPIR-V
// CHECK: ; Version: 1.0
// CHECK: ; Generator: Codeplay; 0
// CHECK: ; Bound: 40
// CHECK: ; Schema: 0
// CHECK: OpCapability Shader
// CHECK: OpCapability VariablePointers
// CHECK: OpExtension "SPV_KHR_variable_pointers"
// CHECK: OpMemoryModel Logical GLSL450
// CHECK: OpEntryPoint GLCompute %[[FOO_ID:[a-zA-Z0-9_]*]] "foo"
// CHECK: OpExecutionMode %[[FOO_ID]] LocalSize 1 1 1
// CHECK: OpMemberDecorate %[[FLOAT_ARG_STRUCT_TYPE_ID:[a-zA-Z0-9_]*]] 0 Offset 0
// CHECK: OpDecorate %[[FLOAT_ARG_STRUCT_TYPE_ID]] Block
// CHECK: OpDecorate %[[INT_DYNAMIC_ARRAY_TYPE_ID:[a-zA-Z0-9_]*]] ArrayStride 16
// CHECK: OpMemberDecorate %[[INT_ARG_STRUCT_TYPE_ID:[a-zA-Z0-9_]*]] 0 Offset 0
// CHECK: OpDecorate %[[INT_ARG_STRUCT_TYPE_ID]] Block
// CHECK: OpDecorate %[[ARG0_ID:[a-zA-Z0-9_]*]] DescriptorSet 0
// CHECK: OpDecorate %[[ARG0_ID]] Binding 0
// CHECK: OpDecorate %[[ARG1_ID:[a-zA-Z0-9_]*]] DescriptorSet 0
// CHECK: OpDecorate %[[ARG1_ID]] Binding 1
// CHECK: OpDecorate %[[ARG2_ID:[a-zA-Z0-9_]*]] DescriptorSet 0
// CHECK: OpDecorate %[[ARG2_ID]] Binding 2
// CHECK: OpDecorate %[[ARG3_ID:[a-zA-Z0-9_]*]] DescriptorSet 0
// CHECK: OpDecorate %[[ARG3_ID]] Binding 3
// CHECK: OpDecorate %[[ARG4_ID:[a-zA-Z0-9_]*]] DescriptorSet 0
// CHECK: OpDecorate %[[ARG4_ID]] Binding 4
// CHECK-DAG: %[[FLOAT_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeFloat 32
// CHECK-DAG: %[[FLOAT_VECTOR_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeVector %[[FLOAT_TYPE_ID]] 4
// CHECK-DAG: %[[FLOAT_ARG_STRUCT_TYPE_ID]] = OpTypeStruct %[[FLOAT_VECTOR_TYPE_ID]]
// CHECK-DAG: %[[FLOAT_GLOBAL_POINTER_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypePointer StorageBuffer %[[FLOAT_ARG_STRUCT_TYPE_ID]]
// CHECK-DAG: %[[INT_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeInt 32 0
// CHECK-DAG: %[[INT_VECTOR_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeVector %[[INT_TYPE_ID]] 4
// CHECK-DAG: %[[INT_DYNAMIC_ARRAY_TYPE_ID]] = OpTypeRuntimeArray %[[INT_VECTOR_TYPE_ID]]
// CHECK-DAG: %[[INT_ARG_STRUCT_TYPE_ID]] = OpTypeStruct %[[INT_DYNAMIC_ARRAY_TYPE_ID]]
// CHECK-DAG: %[[INT_GLOBAL_POINTER_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypePointer StorageBuffer %[[INT_ARG_STRUCT_TYPE_ID]]
// CHECK-DAG: %[[VOID_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeVoid
// CHECK-DAG: %[[FOO_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeFunction %[[VOID_TYPE_ID]]
// CHECK-DAG: %[[FLOAT_ARG_POINTER_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypePointer StorageBuffer %[[FLOAT_VECTOR_TYPE_ID]]
// CHECK-DAG: %[[INT_ARG_POINTER_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypePointer StorageBuffer %[[INT_VECTOR_TYPE_ID]]
// CHECK: %[[BOOL_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeBool
// CHECK: %[[BOOL_VECTOR_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeVector %[[BOOL_TYPE_ID]] 4
// CHECK: %[[CONSTANT_NULL_ID:[a-zA-Z0-9]*]] = OpConstantNull %[[INT_VECTOR_TYPE_ID]]
// CHECK: %[[CONSTANT_MAXINT_ID:[a-zA-Z0-9_]*]] = OpConstant %[[INT_TYPE_ID]] 4294967295
// CHECK: %[[CONSTANT_MAXINT_VECTOR_ID:[a-zA-Z0-9]*]] = OpConstantComposite %[[INT_VECTOR_TYPE_ID]] %[[CONSTANT_MAXINT_ID]] %[[CONSTANT_MAXINT_ID]] %[[CONSTANT_MAXINT_ID]] %[[CONSTANT_MAXINT_ID]]
// CHECK: %[[CONSTANT_0_ID:[a-zA-Z0-9_]*]] = OpConstant %[[INT_TYPE_ID]] 0
// CHECK: %[[ARG0_ID]] = OpVariable %[[FLOAT_GLOBAL_POINTER_TYPE_ID]] StorageBuffer
// CHECK: %[[ARG1_ID]] = OpVariable %[[FLOAT_GLOBAL_POINTER_TYPE_ID]] StorageBuffer
// CHECK: %[[ARG2_ID]] = OpVariable %[[FLOAT_GLOBAL_POINTER_TYPE_ID]] StorageBuffer
// CHECK: %[[ARG3_ID]] = OpVariable %[[FLOAT_GLOBAL_POINTER_TYPE_ID]] StorageBuffer
// CHECK: %[[ARG4_ID]] = OpVariable %[[INT_GLOBAL_POINTER_TYPE_ID]] StorageBuffer

// CHECK: %[[FOO_ID]] = OpFunction %[[VOID_TYPE_ID]] None %[[FOO_TYPE_ID]]
// CHECK: %[[LABEL_ID:[a-zA-Z0-9_]*]] = OpLabel
// CHECK: %[[A_ACCESS_CHAIN_ID:[a-zA-Z0-9_]*]] = OpAccessChain %[[FLOAT_ARG_POINTER_TYPE_ID]] %[[ARG0_ID]] %[[CONSTANT_0_ID]]
// CHECK: %[[LOADA_ID:[a-zA-Z0-9_]*]] = OpLoad %[[FLOAT_VECTOR_TYPE_ID]] %[[A_ACCESS_CHAIN_ID]]
// CHECK: %[[B_ACCESS_CHAIN_ID:[a-zA-Z0-9_]*]] = OpAccessChain %[[FLOAT_ARG_POINTER_TYPE_ID]] %[[ARG1_ID]] %[[CONSTANT_0_ID]]
// CHECK: %[[LOADB_ID:[a-zA-Z0-9_]*]] = OpLoad %[[FLOAT_VECTOR_TYPE_ID]] %[[B_ACCESS_CHAIN_ID]]
// CHECK: %[[C_ACCESS_CHAIN_ID:[a-zA-Z0-9_]*]] = OpAccessChain %[[FLOAT_ARG_POINTER_TYPE_ID]] %[[ARG2_ID]] %[[CONSTANT_0_ID]]
// CHECK: %[[LOADC_ID:[a-zA-Z0-9_]*]] = OpLoad %[[FLOAT_VECTOR_TYPE_ID]] %[[C_ACCESS_CHAIN_ID]]
// CHECK: %[[D_ACCESS_CHAIN_ID:[a-zA-Z0-9_]*]] = OpAccessChain %[[FLOAT_ARG_POINTER_TYPE_ID]] %[[ARG3_ID]] %[[CONSTANT_0_ID]]
// CHECK: %[[LOADD_ID:[a-zA-Z0-9_]*]] = OpLoad %[[FLOAT_VECTOR_TYPE_ID]] %[[D_ACCESS_CHAIN_ID]]
// CHECK: %[[O_ACCESS_CHAIN_ID:[a-zA-Z0-9_]*]] = OpAccessChain %[[INT_ARG_POINTER_TYPE_ID]] %[[ARG4_ID]] %[[CONSTANT_0_ID]] %[[CONSTANT_0_ID]]
// CHECK: %[[COMP1_RES_ID:[a-zA-Z0-9]*]] = OpFOrdLessThanEqual %[[BOOL_VECTOR_TYPE_ID]] %[[LOADA_ID]] %[[LOADB_ID]]
// CHECK: %[[COMP2_RES_ID:[a-zA-Z0-9]*]] = OpFOrdGreaterThan %[[BOOL_VECTOR_TYPE_ID]] %[[LOADC_ID]] %[[LOADD_ID]]
// CHECK: %[[LOGICAL_RES_ID:[a-zA-Z0-9]*]] = OpLogicalAnd %[[BOOL_VECTOR_TYPE_ID]] %[[COMP2_RES_ID]] %[[COMP1_RES_ID]]
// CHECK: %[[SELECT_ID:[a-zA-Z0-9]*]] = OpSelect %[[INT_VECTOR_TYPE_ID]] %[[LOGICAL_RES_ID]] %[[CONSTANT_MAXINT_VECTOR_ID]] %[[CONSTANT_NULL_ID]]
// CHECK: OpStore %[[O_ACCESS_CHAIN_ID]] %[[SELECT_ID]]
// CHECK: OpReturn
// CHECK: OpFunctionEnd

void kernel __attribute__((reqd_work_group_size(1, 1, 1))) foo(float4 a, float4 b, float4 c, float4 d, global int4 *o)
{
int4 ab = (a <= b);
int4 cd = (c > d);
*o = (ab && cd);
}
83 changes: 83 additions & 0 deletions test/bool_vector_or.cl
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// RUN: clspv %s -S -o %t.spvasm
// RUN: FileCheck %s < %t.spvasm
// RUN: clspv %s -o %t.spv
// RUN: spirv-dis -o %t2.spvasm %t.spv
// RUN: FileCheck %s < %t2.spvasm
// RUN: spirv-val --target-env vulkan1.0 %t.spv

// CHECK: ; SPIR-V
// CHECK: ; Version: 1.0
// CHECK: ; Generator: Codeplay; 0
// CHECK: ; Bound: 40
// CHECK: ; Schema: 0
// CHECK: OpCapability Shader
// CHECK: OpCapability VariablePointers
// CHECK: OpExtension "SPV_KHR_variable_pointers"
// CHECK: OpMemoryModel Logical GLSL450
// CHECK: OpEntryPoint GLCompute %[[FOO_ID:[a-zA-Z0-9_]*]] "foo"
// CHECK: OpExecutionMode %[[FOO_ID]] LocalSize 1 1 1
// CHECK: OpMemberDecorate %[[FLOAT_ARG_STRUCT_TYPE_ID:[a-zA-Z0-9_]*]] 0 Offset 0
// CHECK: OpDecorate %[[FLOAT_ARG_STRUCT_TYPE_ID]] Block
// CHECK: OpDecorate %[[INT_DYNAMIC_ARRAY_TYPE_ID:[a-zA-Z0-9_]*]] ArrayStride 16
// CHECK: OpMemberDecorate %[[INT_ARG_STRUCT_TYPE_ID:[a-zA-Z0-9_]*]] 0 Offset 0
// CHECK: OpDecorate %[[INT_ARG_STRUCT_TYPE_ID]] Block
// CHECK: OpDecorate %[[ARG0_ID:[a-zA-Z0-9_]*]] DescriptorSet 0
// CHECK: OpDecorate %[[ARG0_ID]] Binding 0
// CHECK: OpDecorate %[[ARG1_ID:[a-zA-Z0-9_]*]] DescriptorSet 0
// CHECK: OpDecorate %[[ARG1_ID]] Binding 1
// CHECK: OpDecorate %[[ARG2_ID:[a-zA-Z0-9_]*]] DescriptorSet 0
// CHECK: OpDecorate %[[ARG2_ID]] Binding 2
// CHECK: OpDecorate %[[ARG3_ID:[a-zA-Z0-9_]*]] DescriptorSet 0
// CHECK: OpDecorate %[[ARG3_ID]] Binding 3
// CHECK: OpDecorate %[[ARG4_ID:[a-zA-Z0-9_]*]] DescriptorSet 0
// CHECK: OpDecorate %[[ARG4_ID]] Binding 4
// CHECK-DAG: %[[FLOAT_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeFloat 32
// CHECK-DAG: %[[FLOAT_VECTOR_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeVector %[[FLOAT_TYPE_ID]] 4
// CHECK-DAG: %[[FLOAT_ARG_STRUCT_TYPE_ID]] = OpTypeStruct %[[FLOAT_VECTOR_TYPE_ID]]
// CHECK-DAG: %[[FLOAT_GLOBAL_POINTER_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypePointer StorageBuffer %[[FLOAT_ARG_STRUCT_TYPE_ID]]
// CHECK-DAG: %[[INT_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeInt 32 0
// CHECK-DAG: %[[INT_VECTOR_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeVector %[[INT_TYPE_ID]] 4
// CHECK-DAG: %[[INT_DYNAMIC_ARRAY_TYPE_ID]] = OpTypeRuntimeArray %[[INT_VECTOR_TYPE_ID]]
// CHECK-DAG: %[[INT_ARG_STRUCT_TYPE_ID]] = OpTypeStruct %[[INT_DYNAMIC_ARRAY_TYPE_ID]]
// CHECK-DAG: %[[INT_GLOBAL_POINTER_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypePointer StorageBuffer %[[INT_ARG_STRUCT_TYPE_ID]]
// CHECK-DAG: %[[VOID_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeVoid
// CHECK-DAG: %[[FOO_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeFunction %[[VOID_TYPE_ID]]
// CHECK-DAG: %[[FLOAT_ARG_POINTER_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypePointer StorageBuffer %[[FLOAT_VECTOR_TYPE_ID]]
// CHECK-DAG: %[[INT_ARG_POINTER_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypePointer StorageBuffer %[[INT_VECTOR_TYPE_ID]]
// CHECK: %[[BOOL_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeBool
// CHECK: %[[BOOL_VECTOR_TYPE_ID:[a-zA-Z0-9_]*]] = OpTypeVector %[[BOOL_TYPE_ID]] 4
// CHECK: %[[CONSTANT_NULL_ID:[a-zA-Z0-9]*]] = OpConstantNull %[[INT_VECTOR_TYPE_ID]]
// CHECK: %[[CONSTANT_MAXINT_ID:[a-zA-Z0-9_]*]] = OpConstant %[[INT_TYPE_ID]] 4294967295
// CHECK: %[[CONSTANT_MAXINT_VECTOR_ID:[a-zA-Z0-9]*]] = OpConstantComposite %[[INT_VECTOR_TYPE_ID]] %[[CONSTANT_MAXINT_ID]] %[[CONSTANT_MAXINT_ID]] %[[CONSTANT_MAXINT_ID]] %[[CONSTANT_MAXINT_ID]]
// CHECK: %[[CONSTANT_0_ID:[a-zA-Z0-9_]*]] = OpConstant %[[INT_TYPE_ID]] 0
// CHECK: %[[ARG0_ID]] = OpVariable %[[FLOAT_GLOBAL_POINTER_TYPE_ID]] StorageBuffer
// CHECK: %[[ARG1_ID]] = OpVariable %[[FLOAT_GLOBAL_POINTER_TYPE_ID]] StorageBuffer
// CHECK: %[[ARG2_ID]] = OpVariable %[[FLOAT_GLOBAL_POINTER_TYPE_ID]] StorageBuffer
// CHECK: %[[ARG3_ID]] = OpVariable %[[FLOAT_GLOBAL_POINTER_TYPE_ID]] StorageBuffer
// CHECK: %[[ARG4_ID]] = OpVariable %[[INT_GLOBAL_POINTER_TYPE_ID]] StorageBuffer

// CHECK: %[[FOO_ID]] = OpFunction %[[VOID_TYPE_ID]] None %[[FOO_TYPE_ID]]
// CHECK: %[[LABEL_ID:[a-zA-Z0-9_]*]] = OpLabel
// CHECK: %[[A_ACCESS_CHAIN_ID:[a-zA-Z0-9_]*]] = OpAccessChain %[[FLOAT_ARG_POINTER_TYPE_ID]] %[[ARG0_ID]] %[[CONSTANT_0_ID]]
// CHECK: %[[LOADA_ID:[a-zA-Z0-9_]*]] = OpLoad %[[FLOAT_VECTOR_TYPE_ID]] %[[A_ACCESS_CHAIN_ID]]
// CHECK: %[[B_ACCESS_CHAIN_ID:[a-zA-Z0-9_]*]] = OpAccessChain %[[FLOAT_ARG_POINTER_TYPE_ID]] %[[ARG1_ID]] %[[CONSTANT_0_ID]]
// CHECK: %[[LOADB_ID:[a-zA-Z0-9_]*]] = OpLoad %[[FLOAT_VECTOR_TYPE_ID]] %[[B_ACCESS_CHAIN_ID]]
// CHECK: %[[C_ACCESS_CHAIN_ID:[a-zA-Z0-9_]*]] = OpAccessChain %[[FLOAT_ARG_POINTER_TYPE_ID]] %[[ARG2_ID]] %[[CONSTANT_0_ID]]
// CHECK: %[[LOADC_ID:[a-zA-Z0-9_]*]] = OpLoad %[[FLOAT_VECTOR_TYPE_ID]] %[[C_ACCESS_CHAIN_ID]]
// CHECK: %[[D_ACCESS_CHAIN_ID:[a-zA-Z0-9_]*]] = OpAccessChain %[[FLOAT_ARG_POINTER_TYPE_ID]] %[[ARG3_ID]] %[[CONSTANT_0_ID]]
// CHECK: %[[LOADD_ID:[a-zA-Z0-9_]*]] = OpLoad %[[FLOAT_VECTOR_TYPE_ID]] %[[D_ACCESS_CHAIN_ID]]
// CHECK: %[[O_ACCESS_CHAIN_ID:[a-zA-Z0-9_]*]] = OpAccessChain %[[INT_ARG_POINTER_TYPE_ID]] %[[ARG4_ID]] %[[CONSTANT_0_ID]] %[[CONSTANT_0_ID]]
// CHECK: %[[COMP1_RES_ID:[a-zA-Z0-9]*]] = OpFOrdLessThanEqual %[[BOOL_VECTOR_TYPE_ID]] %[[LOADA_ID]] %[[LOADB_ID]]
// CHECK: %[[COMP2_RES_ID:[a-zA-Z0-9]*]] = OpFOrdGreaterThan %[[BOOL_VECTOR_TYPE_ID]] %[[LOADC_ID]] %[[LOADD_ID]]
// CHECK: %[[LOGICAL_RES_ID:[a-zA-Z0-9]*]] = OpLogicalOr %[[BOOL_VECTOR_TYPE_ID]] %[[COMP2_RES_ID]] %[[COMP1_RES_ID]]
// CHECK: %[[SELECT_ID:[a-zA-Z0-9]*]] = OpSelect %[[INT_VECTOR_TYPE_ID]] %[[LOGICAL_RES_ID]] %[[CONSTANT_MAXINT_VECTOR_ID]] %[[CONSTANT_NULL_ID]]
// CHECK: OpStore %[[O_ACCESS_CHAIN_ID]] %[[SELECT_ID]]
// CHECK: OpReturn
// CHECK: OpFunctionEnd

void kernel __attribute__((reqd_work_group_size(1, 1, 1))) foo(float4 a, float4 b, float4 c, float4 d, global int4 *o)
{
int4 ab = (a <= b);
int4 cd = (c > d);
*o = (ab || cd);
}

0 comments on commit 24272b6

Please sign in to comment.