Skip to content

Commit

Permalink
Fix and/or intrinsics with non-int parameters (microsoft#7060)
Browse files Browse the repository at this point in the history
And/or intrinsics were set to allow any parameters, which is consistent
with the behavior of the && and || operators they were meant to replace,
however this meant that if they were passed floating point values, those
values would be applied to the binary and/or operands, which isn't
allowed. Instead, they should be converted to booleans to be consistent
with the behavior of && and ||. This can be done simply by restricting
the parameters to booleans which forces the appropriate conversions.
Adds tests for for using bools, ints, and floats in scalars, different
sized vectors, and matrices as parameters to or and and.

Fixes: microsoft#7057
FIxes: microsoft#6995
  • Loading branch information
pow2clk authored Jan 22, 2025
1 parent b148329 commit 25faa88
Show file tree
Hide file tree
Showing 5 changed files with 386 additions and 2 deletions.
141 changes: 141 additions & 0 deletions tools/clang/test/CodeGenHLSL/vector-and.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// RUN: %dxc -T ps_6_0 -HV 2021 -DTYPE=bool %s | FileCheck %s --check-prefixes=CHECK,I32
// RUN: %dxc -T ps_6_0 -HV 2018 -DTYPE=bool %s | FileCheck %s --check-prefixes=CHECK,I32
// RUN: %dxc -T ps_6_0 -HV 2021 -DTYPE=int %s | FileCheck %s --check-prefixes=CHECK,I32
// RUN: %dxc -T ps_6_0 -HV 2018 -DTYPE=int %s | FileCheck %s --check-prefixes=CHECK,I32
// RUN: %dxc -T ps_6_0 -HV 2021 -DTYPE=float %s | FileCheck %s --check-prefixes=CHECK,F32
// RUN: %dxc -T ps_6_0 -HV 2018 -DTYPE=float %s | FileCheck %s --check-prefixes=CHECK,F32

// I32: %dx.types.ResRet.[[TY:i32]] = type { [[TYPE:i32]]
// F32: %dx.types.ResRet.[[TY:f32]] = type { [[TYPE:float]]

// CHECK-LABEL: define void @main

ByteAddressBuffer buf;

float4 main() : SV_Target {

// CHECK-DAG: [[SAR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 0
// CHECK-DAG: [[SAX:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[SAR]], 0
// I32-DAG: [[SA:%.*]] = icmp ne i32 [[SAX]], 0
// F32-DAG: [[SA:%.*]] = fcmp fast une float [[SAX]], 0.000000e+00

// CHECK-DAG: [[SBR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 8
// CHECK-DAG: [[SBX:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[SBR]], 0
// I32-DAG: [[SB:%.*]] = icmp ne i32 [[SBX]], 0
// F32-DAG: [[SB:%.*]] = fcmp fast une float [[SBX]], 0.000000e+00

TYPE sb = buf.Load<TYPE>(8);
TYPE sa = buf.Load<TYPE>(0);

// CHECK: and i1 [[SB]], [[SA]]
TYPE res = and(sa, sb);

// CHECK-DAG: [[V1AR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 16
// CHECK-DAG: [[V1AX:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V1AR]], 0
// I32-DAG: [[V1A:%.*]] = icmp ne i32 [[V1AX]], 0
// F32-DAG: [[V1A:%.*]] = fcmp fast une float [[V1AX]], 0.000000e+00

// CHECK-DAG: [[V1BR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 24
// CHECK-DAG: [[V1BX:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V1BR]], 0
// I32-DAG: [[V1B:%.*]] = icmp ne i32 [[V1BX]], 0
// F32-DAG: [[V1B:%.*]] = fcmp fast une float [[V1BX]], 0.000000e+00

vector<TYPE, 1> v1b = buf.Load< vector<TYPE, 1> >(24);
vector<TYPE, 1> v1a = buf.Load< vector<TYPE, 1> >(16);

// CHECK: and i1 [[V1B]], [[V1A]]
vector<TYPE, 1> res1 = and(v1a, v1b);

// CHECK-DAG: [[V3AR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 32
// CHECK-DAG: [[V3AX0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3AR]], 0
// CHECK-DAG: [[V3AX1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3AR]], 1
// CHECK-DAG: [[V3AX2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3AR]], 2

// I32-DAG: [[V3A0:%.*]] = icmp ne i32 [[V3AX0]], 0
// I32-DAG: [[V3A1:%.*]] = icmp ne i32 [[V3AX1]], 0
// I32-DAG: [[V3A2:%.*]] = icmp ne i32 [[V3AX2]], 0

// F32-DAG: [[V3A0:%.*]] = fcmp fast une float [[V3AX0]], 0.000000e+00
// F32-DAG: [[V3A1:%.*]] = fcmp fast une float [[V3AX1]], 0.000000e+00
// F32-DAG: [[V3A2:%.*]] = fcmp fast une float [[V3AX2]], 0.000000e+00

// CHECK-DAG: [[V3BR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 56
// CHECK-DAG: [[V3BX0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3BR]], 0
// CHECK-DAG: [[V3BX1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3BR]], 1
// CHECK-DAG: [[V3BX2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3BR]], 2

// I32-DAG: [[V3B0:%.*]] = icmp ne i32 [[V3BX0]], 0
// I32-DAG: [[V3B1:%.*]] = icmp ne i32 [[V3BX1]], 0
// I32-DAG: [[V3B2:%.*]] = icmp ne i32 [[V3BX2]], 0

// F32-DAG: [[V3B0:%.*]] = fcmp fast une float [[V3BX0]], 0.000000e+00
// F32-DAG: [[V3B1:%.*]] = fcmp fast une float [[V3BX1]], 0.000000e+00
// F32-DAG: [[V3B2:%.*]] = fcmp fast une float [[V3BX2]], 0.000000e+00

vector<TYPE, 3> v3b = buf.Load< vector<TYPE, 3> >(56);
vector<TYPE, 3> v3a = buf.Load< vector<TYPE, 3> >(32);

// CHECK: and i1 [[V3B0]], [[V3A0]]
// CHECK: and i1 [[V3B1]], [[V3A1]]
// CHECK: and i1 [[V3B2]], [[V3A2]]
vector<TYPE, 3> res3 = and(v3a, v3b);

// CHECK-DAG: [[MAR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 80
// CHECK-DAG: [[MAX0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 0
// CHECK-DAG: [[MAX1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 1
// CHECK-DAG: [[MAX2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 2
// CHECK-DAG: [[MAX3:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 3
// CHECK-DAG: [[MAR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 96
// CHECK-DAG: [[MAX4:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 0
// CHECK-DAG: [[MAX5:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 1

// I32-DAG: [[MA0:%.*]] = icmp ne i32 [[MAX0]], 0
// I32-DAG: [[MA1:%.*]] = icmp ne i32 [[MAX1]], 0
// I32-DAG: [[MA2:%.*]] = icmp ne i32 [[MAX2]], 0
// I32-DAG: [[MA3:%.*]] = icmp ne i32 [[MAX3]], 0
// I32-DAG: [[MA4:%.*]] = icmp ne i32 [[MAX4]], 0
// I32-DAG: [[MA5:%.*]] = icmp ne i32 [[MAX5]], 0

// F32-DAG: [[MA0:%.*]] = fcmp fast une float [[MAX0]], 0.000000e+00
// F32-DAG: [[MA1:%.*]] = fcmp fast une float [[MAX1]], 0.000000e+00
// F32-DAG: [[MA2:%.*]] = fcmp fast une float [[MAX2]], 0.000000e+00
// F32-DAG: [[MA3:%.*]] = fcmp fast une float [[MAX3]], 0.000000e+00
// F32-DAG: [[MA4:%.*]] = fcmp fast une float [[MAX4]], 0.000000e+00
// F32-DAG: [[MA5:%.*]] = fcmp fast une float [[MAX5]], 0.000000e+00

// CHECK-DAG: [[MBR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 128
// CHECK-DAG: [[MBX0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 0
// CHECK-DAG: [[MBX1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 1
// CHECK-DAG: [[MBX2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 2
// CHECK-DAG: [[MBX3:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 3
// CHECK-DAG: [[MBR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 144
// CHECK-DAG: [[MBX4:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 0
// CHECK-DAG: [[MBX5:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 1

// I32-DAG: [[MB0:%.*]] = icmp ne i32 [[MBX0]], 0
// I32-DAG: [[MB1:%.*]] = icmp ne i32 [[MBX1]], 0
// I32-DAG: [[MB2:%.*]] = icmp ne i32 [[MBX2]], 0
// I32-DAG: [[MB3:%.*]] = icmp ne i32 [[MBX3]], 0
// I32-DAG: [[MB4:%.*]] = icmp ne i32 [[MBX4]], 0
// I32-DAG: [[MB5:%.*]] = icmp ne i32 [[MBX5]], 0

// F32-DAG: [[MB0:%.*]] = fcmp fast une float [[MBX0]], 0.000000e+00
// F32-DAG: [[MB1:%.*]] = fcmp fast une float [[MBX1]], 0.000000e+00
// F32-DAG: [[MB2:%.*]] = fcmp fast une float [[MBX2]], 0.000000e+00
// F32-DAG: [[MB3:%.*]] = fcmp fast une float [[MBX3]], 0.000000e+00
// F32-DAG: [[MB4:%.*]] = fcmp fast une float [[MBX4]], 0.000000e+00
// F32-DAG: [[MB5:%.*]] = fcmp fast une float [[MBX5]], 0.000000e+00

matrix<TYPE, 2, 3> matb = buf.Load< matrix<TYPE, 2, 3> >(128);
matrix<TYPE, 2, 3> mata = buf.Load< matrix<TYPE, 2, 3> >(80);

// CHECK: and i1 [[MB0]], [[MA0]]
// CHECK: and i1 [[MB1]], [[MA1]]
// CHECK: and i1 [[MB2]], [[MA2]]
// CHECK: and i1 [[MB3]], [[MA3]]
// CHECK: and i1 [[MB4]], [[MA4]]
// CHECK: and i1 [[MB5]], [[MA5]]
matrix<TYPE, 2, 3> resmat = and(mata, matb);

return float4(res3 + resmat[0] + resmat[1], res + res1.x);
}
164 changes: 164 additions & 0 deletions tools/clang/test/CodeGenHLSL/vector-or.hlsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// RUN: %dxc -T ps_6_0 -HV 2021 -DTYPE=bool %s | FileCheck %s --check-prefixes=CHECK,I32
// RUN: %dxc -T ps_6_0 -HV 2018 -DTYPE=bool %s | FileCheck %s --check-prefixes=CHECK,I32
// RUN: %dxc -T ps_6_0 -HV 2021 -DTYPE=int %s | FileCheck %s --check-prefixes=CHECK,I32
// RUN: %dxc -T ps_6_0 -HV 2018 -DTYPE=int %s | FileCheck %s --check-prefixes=CHECK,I32
// RUN: %dxc -T ps_6_0 -HV 2021 -DTYPE=float %s | FileCheck %s --check-prefixes=CHECK,F32
// RUN: %dxc -T ps_6_0 -HV 2018 -DTYPE=float %s | FileCheck %s --check-prefixes=CHECK,F32

// I32: %dx.types.ResRet.[[TY:i32]] = type { [[TYPE:i32]]
// F32: %dx.types.ResRet.[[TY:f32]] = type { [[TYPE:float]]

// CHECK-LABEL: define void @main

ByteAddressBuffer buf;

float4 main() : SV_Target {

// CHECK: [[SAR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 0
// F32: [[SAX:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[SAR]], 0
// I32: [[SA:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[SAR]], 0

// CHECK: [[SBR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 8
// F32: [[SBX:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[SBR]], 0
// I32: [[SB:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[SBR]], 0

// F32: [[SA:%.*]] = fcmp fast une float [[SAX]], 0.000000e+00
// F32: [[SB:%.*]] = fcmp fast une float [[SBX]], 0.000000e+00

TYPE sa = buf.Load<TYPE>(0);
TYPE sb = buf.Load<TYPE>(8);

// I32: or i32 [[SB]], [[SA]]
// F32: or i1 [[SA]], [[SB]]

TYPE res = or(sb, sa);

// CHECK: [[V1AR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 16
// F32: [[V1AX:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V1AR]], 0
// I32: [[V1A:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V1AR]], 0

// CHECK: [[V1BR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 24
// F32: [[V1BX:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V1BR]], 0
// I32: [[V1B:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V1BR]], 0

// F32: [[V1B:%.*]] = fcmp fast une float [[V1BX]], 0.000000e+00
// F32: [[V1A:%.*]] = fcmp fast une float [[V1AX]], 0.000000e+00

vector<TYPE, 1> v1a = buf.Load< vector<TYPE, 1> >(16);
vector<TYPE, 1> v1b = buf.Load< vector<TYPE, 1> >(24);

// I32: or i32 [[V1B]], [[V1A]]
// F32: or i1 [[V1A]], [[V1B]]

vector<TYPE, 1> res1 = or(v1a, v1b);

// CHECK: [[V3AR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 32
// F32: [[V3AX0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3AR]], 0
// F32: [[V3AX1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3AR]], 1
// F32: [[V3AX2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3AR]], 2

// I32: [[V3A0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3AR]], 0
// I32: [[V3A1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3AR]], 1
// I32: [[V3A2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3AR]], 2

// CHECK: [[V3BR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 56
// F32: [[V3BX0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3BR]], 0
// F32: [[V3BX1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3BR]], 1
// F32: [[V3BX2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3BR]], 2

// I32: [[V3B0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3BR]], 0
// I32: [[V3B1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3BR]], 1
// I32: [[V3B2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[V3BR]], 2

// F32: [[V3B0:%.*]] = fcmp fast une float [[V3BX0]], 0.000000e+00
// F32: [[V3B1:%.*]] = fcmp fast une float [[V3BX1]], 0.000000e+00
// F32: [[V3B2:%.*]] = fcmp fast une float [[V3BX2]], 0.000000e+00

// F32: [[V3A0:%.*]] = fcmp fast une float [[V3AX0]], 0.000000e+00
// F32: [[V3A1:%.*]] = fcmp fast une float [[V3AX1]], 0.000000e+00
// F32: [[V3A2:%.*]] = fcmp fast une float [[V3AX2]], 0.000000e+00

vector<TYPE, 3> v3a = buf.Load< vector<TYPE, 3> >(32);
vector<TYPE, 3> v3b = buf.Load< vector<TYPE, 3> >(56);

// I32: or i32 [[V3B0]], [[V3A0]]
// I32: or i32 [[V3B1]], [[V3A1]]
// I32: or i32 [[V3B2]], [[V3A2]]

// F32: or i1 [[V3A0]], [[V3B0]]
// F32: or i1 [[V3A1]], [[V3B1]]
// F32: or i1 [[V3A2]], [[V3B2]]

vector<TYPE, 3> res3 = or(v3a, v3b);

// CHECK: [[MAR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 80
// F32: [[MAX0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 0
// F32: [[MAX1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 1
// F32: [[MAX2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 2
// F32: [[MAX3:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 3

// I32: [[MA0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 0
// I32: [[MA1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 1
// I32: [[MA2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 2
// I32: [[MA3:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 3

// CHECK: [[MAR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 96
// F32: [[MAX4:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 0
// F32: [[MAX5:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 1

// I32: [[MA4:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 0
// I32: [[MA5:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MAR]], 1

// CHECK: [[MBR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 128
// F32: [[MBX0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 0
// F32: [[MBX1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 1
// F32: [[MBX2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 2
// F32: [[MBX3:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 3

// I32: [[MB0:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 0
// I32: [[MB1:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 1
// I32: [[MB2:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 2
// I32: [[MB3:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 3

// CHECK: [[MBR:%.*]] = call %dx.types.ResRet.[[TY]] @dx.op.bufferLoad.[[TY]](i32 68, %dx.types.Handle %{{.*}}, i32 144
// F32: [[MBX4:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 0
// F32: [[MBX5:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 1

// I32: [[MB4:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 0
// I32: [[MB5:%.*]] = extractvalue %dx.types.ResRet.[[TY]] [[MBR]], 1

// F32: [[MB0:%.*]] = fcmp fast une float [[MBX0]], 0.000000e+00
// F32: [[MB1:%.*]] = fcmp fast une float [[MBX1]], 0.000000e+00
// F32: [[MB2:%.*]] = fcmp fast une float [[MBX2]], 0.000000e+00
// F32: [[MB3:%.*]] = fcmp fast une float [[MBX3]], 0.000000e+00
// F32: [[MB4:%.*]] = fcmp fast une float [[MBX4]], 0.000000e+00
// F32: [[MB5:%.*]] = fcmp fast une float [[MBX5]], 0.000000e+00

// F32: [[MA0:%.*]] = fcmp fast une float [[MAX0]], 0.000000e+00
// F32: [[MA1:%.*]] = fcmp fast une float [[MAX1]], 0.000000e+00
// F32: [[MA2:%.*]] = fcmp fast une float [[MAX2]], 0.000000e+00
// F32: [[MA3:%.*]] = fcmp fast une float [[MAX3]], 0.000000e+00
// F32: [[MA4:%.*]] = fcmp fast une float [[MAX4]], 0.000000e+00
// F32: [[MA5:%.*]] = fcmp fast une float [[MAX5]], 0.000000e+00

matrix<TYPE, 2, 3> mata = buf.Load< matrix<TYPE, 2, 3> >(80);
matrix<TYPE, 2, 3> matb = buf.Load< matrix<TYPE, 2, 3> >(128);

// I32: or i32 [[MB0]], [[MA0]]
// I32: or i32 [[MB1]], [[MA1]]
// I32: or i32 [[MB2]], [[MA2]]
// I32: or i32 [[MB3]], [[MA3]]
// I32: or i32 [[MB4]], [[MA4]]
// I32: or i32 [[MB5]], [[MA5]]

// F32: or i1 [[MA0]], [[MB0]]
// F32: or i1 [[MA1]], [[MB1]]
// F32: or i1 [[MA2]], [[MB2]]
// F32: or i1 [[MA3]], [[MB3]]
// F32: or i1 [[MA4]], [[MB4]]
// F32: or i1 [[MA5]], [[MB5]]

matrix<TYPE, 2, 3> resmat = or(mata, matb);

return float4(res3 + resmat[0] + resmat[1], res + res1.x);
}
45 changes: 45 additions & 0 deletions tools/clang/test/CodeGenSPIRV/intrinsics.and.hlsl
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// RUN: %dxc -T ps_6_0 -E main -HV 2021 -fcgl %s -spirv | FileCheck %s
// RUN: %dxc -T ps_6_0 -E main -HV 2018 -fcgl %s -spirv | FileCheck %s

// CHECK-DAG: [[v3_0:%[0-9]+]] = OpConstantComposite %v3int %int_0 %int_0 %int_0
// CHECK-DAG: [[v3_1:%[0-9]+]] = OpConstantComposite %v3int %int_1 %int_1 %int_1

void main() {
// CHECK-LABEL: %bb_entry = OpLabel

Expand Down Expand Up @@ -33,4 +36,46 @@ void main() {
// CHECK-NEXT: [[and3:%[0-9]+]] = OpLogicalAnd %bool [[a1]] [[b1]]
// CHECK-NEXT: {{%[0-9]+}} = OpCompositeConstruct %v2bool [[and3]] %true
bool2 t = bool2(and(a, b), true);

int a_0, b_0, c_0;
// Plain assign (scalar)
// CHECK: [[a0_int:%[0-9]+]] = OpLoad %int %a_0
// CHECK-NEXT: [[a0:%[0-9]+]] = OpINotEqual %bool [[a0_int]] %int_0
// CHECK-NEXT: [[b0_int:%[0-9]+]] = OpLoad %int %b_0
// CHECK-NEXT: [[b0:%[0-9]+]] = OpINotEqual %bool [[b0_int]] %int_0
// CHECK-NEXT: [[and0:%[0-9]+]] = OpLogicalAnd %bool [[a0]] [[b0]]
// CHECK-NEXT: [[sel:%[0-9]+]] = OpSelect %int [[and0]] %int_1 %int_0
// CHECK-NEXT: OpStore %c_0 [[sel]]
c_0 = and(a_0, b_0);

int1 i_0, j_0, k_0;
int3 o_0, p_0, q_0;
// Plain assign (vector)
// CHECK-NEXT: [[i0_int:%[0-9]+]] = OpLoad %int %i_0
// CHECK-NEXT: [[i0:%[0-9]+]] = OpINotEqual %bool [[i0_int]] %int_0
// CHECK-NEXT: [[j0_int:%[0-9]+]] = OpLoad %int %j_0
// CHECK-NEXT: [[j0:%[0-9]+]] = OpINotEqual %bool [[j0_int]] %int_0
// CHECK-NEXT: [[and1:%[0-9]+]] = OpLogicalAnd %bool [[i0]] [[j0]]
// CHECK-NEXT: [[sel:%[0-9]+]] = OpSelect %int [[and1]] %int_1 %int_0
// CHECK-NEXT: OpStore %k_0 [[sel]]
k_0 = and(i_0, j_0);

// CHECK-NEXT: [[o0_int:%[0-9]+]] = OpLoad %v3int %o_0
// CHECK-NEXT: [[o0:%[0-9]+]] = OpINotEqual %v3bool [[o0_int]] [[v3_0]]
// CHECK-NEXT: [[p0_int:%[0-9]+]] = OpLoad %v3int %p_0
// CHECK-NEXT: [[p0:%[0-9]+]] = OpINotEqual %v3bool [[p0_int]] [[v3_0]]
// CHECK-NEXT: [[and2:%[0-9]+]] = OpLogicalAnd %v3bool [[o0]] [[p0]]
// CHECK-NEXT: [[sel:%[0-9]+]] = OpSelect %v3int [[and2]] [[v3_1]] [[v3_0]]
// CHECK-NEXT: OpStore %q_0 [[sel]]
q_0 = and(o_0, p_0);

// The result of '&&' could be 'const bool'. In such cases, make sure
// the result type is correct.
// CHECK: [[a0_int:%[0-9]+]] = OpLoad %int %a_0
// CHECK-NEXT: [[a0:%[0-9]+]] = OpINotEqual %bool [[a0_int]] %int_0
// CHECK-NEXT: [[b0_int:%[0-9]+]] = OpLoad %int %b_0
// CHECK-NEXT: [[b0:%[0-9]+]] = OpINotEqual %bool [[b0_int]] %int_0
// CHECK-NEXT: [[and0:%[0-9]+]] = OpLogicalAnd %bool [[a0]] [[b0]]
// CHECK-NEXT: {{%[0-9]+}} = OpCompositeConstruct %v2bool [[and0]] %true
t = bool2(and(a_0, b_0), true);
}
Loading

0 comments on commit 25faa88

Please sign in to comment.