Skip to content

Commit 009e7f1

Browse files
[SPIR-V] Add support for logical operator intrinsics (microsoft#4674)
* [SPIR-V] Add support for logical operator intrinsics Implemented `and`, `or`, and `select`. I used the existing tests for the old behavior of `&&`, `||`, and `?:` in order to verify that they behave as expected (with the caveat of microsoft#4673, but that has the same behavior for DXIL as for SPIR-V). Fixes microsoft#4148 * Clean up * Remove unused variable
1 parent 581cc5a commit 009e7f1

File tree

6 files changed

+272
-14
lines changed

6 files changed

+272
-14
lines changed

tools/clang/lib/SPIRV/SpirvEmitter.cpp

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,7 +1058,10 @@ SpirvInstruction *SpirvEmitter::doExpr(const Expr *expr,
10581058
if (getCompilerInstance().getLangOpts().EnableShortCircuit) {
10591059
result = doShortCircuitedConditionalOperator(condExpr);
10601060
} else {
1061-
result = doConditionalOperator(condExpr);
1061+
const Expr *cond = condExpr->getCond();
1062+
const Expr *falseExpr = condExpr->getFalseExpr();
1063+
const Expr *trueExpr = condExpr->getTrueExpr();
1064+
result = doConditional(condExpr, cond, falseExpr, trueExpr);
10621065
}
10631066
} else if (const auto *defaultArgExpr = dyn_cast<CXXDefaultArgExpr>(expr)) {
10641067
if (defaultArgExpr->getParam()->hasUninstantiatedDefaultArg()) {
@@ -3380,14 +3383,14 @@ SpirvInstruction *SpirvEmitter::doShortCircuitedConditionalOperator(
33803383
return result;
33813384
}
33823385

3383-
SpirvInstruction *
3384-
SpirvEmitter::doConditionalOperator(const ConditionalOperator *expr) {
3386+
SpirvInstruction
3387+
*SpirvEmitter::doConditional(const Expr *expr,
3388+
const Expr *cond,
3389+
const Expr *falseExpr,
3390+
const Expr *trueExpr) {
33853391
const auto type = expr->getType();
33863392
const SourceLocation loc = expr->getExprLoc();
33873393
const SourceRange range = expr->getSourceRange();
3388-
const Expr *cond = expr->getCond();
3389-
const Expr *falseExpr = expr->getFalseExpr();
3390-
const Expr *trueExpr = expr->getTrueExpr();
33913394

33923395
// Corner-case: In HLSL, the condition of the ternary operator can be a
33933396
// matrix of booleans which results in selecting between components of two
@@ -3444,12 +3447,12 @@ SpirvEmitter::doConditionalOperator(const ConditionalOperator *expr) {
34443447
// selection must be a vector of booleans (one per output component).
34453448
uint32_t count = 0;
34463449
if (isVectorType(expr->getType(), nullptr, &count) &&
3447-
!isVectorType(expr->getCond()->getType())) {
3450+
!isVectorType(cond->getType())) {
34483451
const llvm::SmallVector<SpirvInstruction *, 4> components(size_t(count),
34493452
condition);
34503453
condition = spvBuilder.createCompositeConstruct(
34513454
astContext.getExtVectorType(astContext.BoolTy, count), components,
3452-
expr->getCond()->getLocEnd());
3455+
cond->getLocEnd());
34533456
}
34543457

34553458
auto *value = spvBuilder.createSelect(type, condition, trueBranch,
@@ -3475,21 +3478,21 @@ SpirvEmitter::doConditionalOperator(const ConditionalOperator *expr) {
34753478

34763479
// Create the branch instruction. This will end the current basic block.
34773480
spvBuilder.createConditionalBranch(condition, thenBB, elseBB,
3478-
expr->getCond()->getLocEnd(), mergeBB);
3481+
cond->getLocEnd(), mergeBB);
34793482
spvBuilder.addSuccessor(thenBB);
34803483
spvBuilder.addSuccessor(elseBB);
34813484
spvBuilder.setMergeTarget(mergeBB);
34823485
// Handle the then branch
34833486
spvBuilder.setInsertPoint(thenBB);
34843487
spvBuilder.createStore(tempVar, trueBranch,
3485-
expr->getTrueExpr()->getLocStart(), range);
3486-
spvBuilder.createBranch(mergeBB, expr->getTrueExpr()->getLocEnd());
3488+
trueExpr->getLocStart(), range);
3489+
spvBuilder.createBranch(mergeBB, trueExpr->getLocEnd());
34873490
spvBuilder.addSuccessor(mergeBB);
34883491
// Handle the else branch
34893492
spvBuilder.setInsertPoint(elseBB);
34903493
spvBuilder.createStore(tempVar, falseBranch,
3491-
expr->getFalseExpr()->getLocStart(), range);
3492-
spvBuilder.createBranch(mergeBB, expr->getFalseExpr()->getLocEnd());
3494+
falseExpr->getLocStart(), range);
3495+
spvBuilder.createBranch(mergeBB, falseExpr->getLocEnd());
34933496
spvBuilder.addSuccessor(mergeBB);
34943497
// From now on, emit instructions into the merge block.
34953498
spvBuilder.setInsertPoint(mergeBB);
@@ -8249,6 +8252,13 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
82498252
case hlsl::IntrinsicOp::IOP_SetMeshOutputCounts: {
82508253
processMeshOutputCounts(callExpr);
82518254
break;
8255+
}
8256+
case hlsl::IntrinsicOp::IOP_select: {
8257+
const Expr *cond = callExpr->getArg(0);
8258+
const Expr *trueExpr = callExpr->getArg(1);
8259+
const Expr *falseExpr = callExpr->getArg(2);
8260+
retVal = doConditional(callExpr, cond, falseExpr, trueExpr);
8261+
break;
82528262
}
82538263
INTRINSIC_SPIRV_OP_CASE(ddx, DPdx, true);
82548264
INTRINSIC_SPIRV_OP_CASE(ddx_coarse, DPdxCoarse, false);
@@ -8262,6 +8272,8 @@ SpirvEmitter::processIntrinsicCallExpr(const CallExpr *callExpr) {
82628272
INTRINSIC_SPIRV_OP_CASE(fmod, FRem, true);
82638273
INTRINSIC_SPIRV_OP_CASE(fwidth, Fwidth, true);
82648274
INTRINSIC_SPIRV_OP_CASE(reversebits, BitReverse, false);
8275+
INTRINSIC_SPIRV_OP_CASE(and, LogicalAnd, false);
8276+
INTRINSIC_SPIRV_OP_CASE(or, LogicalOr, false);
82658277
INTRINSIC_OP_CASE(round, RoundEven, true);
82668278
INTRINSIC_OP_CASE(uabs, SAbs, true);
82678279
INTRINSIC_OP_CASE_INT_FLOAT(abs, SAbs, FAbs, true);

tools/clang/lib/SPIRV/SpirvEmitter.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ class SpirvEmitter : public ASTConsumer {
122122
SourceRange rangeOverride = {});
123123
SpirvInstruction *doCompoundAssignOperator(const CompoundAssignOperator *);
124124
SpirvInstruction *doConditionalOperator(const ConditionalOperator *expr);
125+
SpirvInstruction *doConditional(const Expr *expr,
126+
const Expr *cond,
127+
const Expr *falseExpr,
128+
const Expr *trueExpr);
125129
SpirvInstruction *
126130
doShortCircuitedConditionalOperator(const ConditionalOperator *expr);
127131
SpirvInstruction *doCXXMemberCallExpr(const CXXMemberCallExpr *expr);
@@ -624,7 +628,7 @@ class SpirvEmitter : public ASTConsumer {
624628
SourceLocation loc);
625629
/// Process spirv intrinsic instruction
626630
SpirvInstruction *processSpvIntrinsicCallExpr(const CallExpr *expr);
627-
631+
628632
/// Process spirv intrinsic type definition
629633
SpirvInstruction *processSpvIntrinsicTypeDef(const CallExpr *expr);
630634

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %dxc -T ps_6_0 -E main -HV 2021
2+
3+
void main() {
4+
// CHECK-LABEL: %bb_entry = OpLabel
5+
6+
bool a, b, c;
7+
// Plain assign (scalar)
8+
// CHECK: [[a0:%\d+]] = OpLoad %bool %a
9+
// CHECK-NEXT: [[b0:%\d+]] = OpLoad %bool %b
10+
// CHECK-NEXT: [[and0:%\d+]] = OpLogicalAnd %bool [[a0]] [[b0]]
11+
// CHECK-NEXT: OpStore %c [[and0]]
12+
c = and(a, b);
13+
14+
bool1 i, j, k;
15+
bool3 o, p, q;
16+
// Plain assign (vector)
17+
// CHECK-NEXT: [[i0:%\d+]] = OpLoad %bool %i
18+
// CHECK-NEXT: [[j0:%\d+]] = OpLoad %bool %j
19+
// CHECK-NEXT: [[and1:%\d+]] = OpLogicalAnd %bool [[i0]] [[j0]]
20+
// CHECK-NEXT: OpStore %k [[and1]]
21+
// CHECK-NEXT: [[o0:%\d+]] = OpLoad %v3bool %o
22+
// CHECK-NEXT: [[p0:%\d+]] = OpLoad %v3bool %p
23+
// CHECK-NEXT: [[and2:%\d+]] = OpLogicalAnd %v3bool [[o0]] [[p0]]
24+
// CHECK-NEXT: OpStore %q [[and2]]
25+
k = and(i, j);
26+
q = and(o, p);
27+
28+
// The result of '&&' could be 'const bool'. In such cases, make sure
29+
// the result type is correct.
30+
// CHECK: [[a1:%\d+]] = OpLoad %bool %a
31+
// CHECK-NEXT: [[b1:%\d+]] = OpLoad %bool %b
32+
// CHECK-NEXT: [[and3:%\d+]] = OpLogicalAnd %bool [[a1]] [[b1]]
33+
// CHECK-NEXT: {{%\d+}} = OpCompositeConstruct %v2bool [[and3]] %true
34+
bool2 t = bool2(and(a, b), true);
35+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %dxc -T ps_6_0 -E main -HV 2021
2+
3+
void main() {
4+
// CHECK-LABEL: %bb_entry = OpLabel
5+
6+
bool a, b, c;
7+
// Plain assign (scalar)
8+
// CHECK: [[a0:%\d+]] = OpLoad %bool %a
9+
// CHECK-NEXT: [[b0:%\d+]] = OpLoad %bool %b
10+
// CHECK-NEXT: [[or0:%\d+]] = OpLogicalOr %bool [[a0]] [[b0]]
11+
// CHECK-NEXT: OpStore %c [[or0]]
12+
c = or(a, b);
13+
14+
bool1 i, j, k;
15+
bool3 o, p, q;
16+
// Plain assign (vector)
17+
// CHECK-NEXT: [[i0:%\d+]] = OpLoad %bool %i
18+
// CHECK-NEXT: [[j0:%\d+]] = OpLoad %bool %j
19+
// CHECK-NEXT: [[or1:%\d+]] = OpLogicalOr %bool [[i0]] [[j0]]
20+
// CHECK-NEXT: OpStore %k [[or1]]
21+
// CHECK-NEXT: [[o0:%\d+]] = OpLoad %v3bool %o
22+
// CHECK-NEXT: [[p0:%\d+]] = OpLoad %v3bool %p
23+
// CHECK-NEXT: [[or2:%\d+]] = OpLogicalOr %v3bool [[o0]] [[p0]]
24+
// CHECK-NEXT: OpStore %q [[or2]]
25+
k = or(i, j);
26+
q = or(o, p);
27+
}
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
// RUN: %dxc -T ps_6_0 -E main -HV 2021
2+
3+
// CHECK: [[v3i0:%\d+]] = OpConstantComposite %v3int %int_0 %int_0 %int_0
4+
5+
uint foo() { return 1; }
6+
float bar() { return 3.0; }
7+
uint zoo();
8+
9+
void main() {
10+
// CHECK-LABEL: %bb_entry = OpLabel
11+
12+
// CHECK: %temp_var_ternary = OpVariable %_ptr_Function_mat2v3float Function
13+
// CHECK: %temp_var_ternary_0 = OpVariable %_ptr_Function_mat2v3float Function
14+
15+
bool b0;
16+
int m, n, o;
17+
// Plain assign (scalar)
18+
// CHECK: [[b0:%\d+]] = OpLoad %bool %b0
19+
// CHECK-NEXT: [[m0:%\d+]] = OpLoad %int %m
20+
// CHECK-NEXT: [[n0:%\d+]] = OpLoad %int %n
21+
// CHECK-NEXT: [[s0:%\d+]] = OpSelect %int [[b0]] [[m0]] [[n0]]
22+
// CHECK-NEXT: OpStore %o [[s0]]
23+
o = select(b0, m, n);
24+
25+
bool1 b1;
26+
bool3 b3;
27+
uint1 p, q, r;
28+
float3 x, y, z;
29+
// Plain assign (vector)
30+
// CHECK-NEXT: [[b1:%\d+]] = OpLoad %bool %b1
31+
// CHECK-NEXT: [[p0:%\d+]] = OpLoad %uint %p
32+
// CHECK-NEXT: [[q0:%\d+]] = OpLoad %uint %q
33+
// CHECK-NEXT: [[s1:%\d+]] = OpSelect %uint [[b1]] [[p0]] [[q0]]
34+
// CHECK-NEXT: OpStore %r [[s1]]
35+
r = select(b1, p, q);
36+
// CHECK-NEXT: [[b3:%\d+]] = OpLoad %v3bool %b3
37+
// CHECK-NEXT: [[x0:%\d+]] = OpLoad %v3float %x
38+
// CHECK-NEXT: [[y0:%\d+]] = OpLoad %v3float %y
39+
// CHECK-NEXT: [[s2:%\d+]] = OpSelect %v3float [[b3]] [[x0]] [[y0]]
40+
// CHECK-NEXT: OpStore %z [[s2]]
41+
z = select(b3, x, y);
42+
43+
// Try condition with various type.
44+
// Note: the SPIR-V OpSelect selection argument must be the same size as the return type.
45+
int3 u, v, w;
46+
float2x3 umat, vmat, wmat;
47+
bool cond;
48+
bool3 cond3;
49+
float floatCond;
50+
int intCond;
51+
int3 int3Cond;
52+
53+
// CHECK: [[cond3:%\d+]] = OpLoad %v3bool %cond3
54+
// CHECK-NEXT: [[u:%\d+]] = OpLoad %v3int %u
55+
// CHECK-NEXT: [[v:%\d+]] = OpLoad %v3int %v
56+
// CHECK-NEXT: {{%\d+}} = OpSelect %v3int [[cond3]] [[u]] [[v]]
57+
w = select(cond3, u, v);
58+
59+
// CHECK: [[cond:%\d+]] = OpLoad %bool %cond
60+
// CHECK-NEXT: [[splat:%\d+]] = OpCompositeConstruct %v3bool [[cond]] [[cond]] [[cond]]
61+
// CHECK-NEXT: [[u:%\d+]] = OpLoad %v3int %u
62+
// CHECK-NEXT: [[v:%\d+]] = OpLoad %v3int %v
63+
// CHECK-NEXT: {{%\d+}} = OpSelect %v3int [[splat]] [[u]] [[v]]
64+
w = select(cond, u, v);
65+
66+
// CHECK: [[floatCond:%\d+]] = OpLoad %float %floatCond
67+
// CHECK-NEXT: [[boolCond:%\d+]] = OpFOrdNotEqual %bool [[floatCond]] %float_0
68+
// CHECK-NEXT: [[bool3Cond:%\d+]] = OpCompositeConstruct %v3bool [[boolCond]] [[boolCond]] [[boolCond]]
69+
// CHECK-NEXT: [[u:%\d+]] = OpLoad %v3int %u
70+
// CHECK-NEXT: [[v:%\d+]] = OpLoad %v3int %v
71+
// CHECK-NEXT: {{%\d+}} = OpSelect %v3int [[bool3Cond]] [[u]] [[v]]
72+
w = select(floatCond, u, v);
73+
74+
// CHECK: [[int3Cond:%\d+]] = OpLoad %v3int %int3Cond
75+
// CHECK-NEXT: [[bool3Cond:%\d+]] = OpINotEqual %v3bool [[int3Cond]] [[v3i0]]
76+
// CHECK-NEXT: [[u:%\d+]] = OpLoad %v3int %u
77+
// CHECK-NEXT: [[v:%\d+]] = OpLoad %v3int %v
78+
// CHECK-NEXT: {{%\d+}} = OpSelect %v3int [[bool3Cond]] [[u]] [[v]]
79+
w = select(int3Cond, u, v);
80+
81+
// CHECK: [[intCond:%\d+]] = OpLoad %int %intCond
82+
// CHECK-NEXT: [[boolCond:%\d+]] = OpINotEqual %bool [[intCond]] %int_0
83+
// CHECK-NEXT: [[umat:%\d+]] = OpLoad %mat2v3float %umat
84+
// CHECK-NEXT: [[vmat:%\d+]] = OpLoad %mat2v3float %vmat
85+
// CHECK-NEXT: OpSelectionMerge %if_merge None
86+
// CHECK-NEXT: OpBranchConditional [[boolCond]] %if_true %if_false
87+
// CHECK-NEXT: %if_true = OpLabel
88+
// CHECK-NEXT: OpStore %temp_var_ternary [[umat]]
89+
// CHECK-NEXT: OpBranch %if_merge
90+
// CHECK-NEXT: %if_false = OpLabel
91+
// CHECK-NEXT: OpStore %temp_var_ternary [[vmat]]
92+
// CHECK-NEXT: OpBranch %if_merge
93+
// CHECK-NEXT: %if_merge = OpLabel
94+
// CHECK-NEXT: [[tempVar:%\d+]] = OpLoad %mat2v3float %temp_var_ternary
95+
// CHECK-NEXT: OpStore %wmat [[tempVar]]
96+
wmat = select(intCond, umat, vmat);
97+
98+
// Make sure literal types are handled correctly in ternary ops
99+
100+
// CHECK: [[b_float:%\d+]] = OpSelect %float {{%\d+}} %float_1_5 %float_2_5
101+
// CHECK-NEXT: {{%\d+}} = OpConvertFToS %int [[b_float]]
102+
int b = select(cond, 1.5, 2.5);
103+
104+
// CHECK: [[a_int:%\d+]] = OpSelect %int {{%\d+}} %int_1 %int_0
105+
// CHECK-NEXT: {{%\d+}} = OpConvertSToF %float [[a_int]]
106+
float a = select(cond, 1, 0);
107+
108+
// CHECK: [[c_long:%\d+]] = OpSelect %long {{%\d+}} %long_3000000000 %long_4000000000
109+
double c = select(cond, 3000000000, 4000000000);
110+
111+
// CHECK: [[d_int:%\d+]] = OpSelect %uint {{%\d+}} %uint_1 %uint_0
112+
uint d = select(cond, 1, 0);
113+
114+
float2x3 e;
115+
float2x3 f;
116+
// CHECK: [[cond:%\d+]] = OpLoad %bool %cond
117+
// CHECK-NEXT: [[e:%\d+]] = OpLoad %mat2v3float %e
118+
// CHECK-NEXT: [[f:%\d+]] = OpLoad %mat2v3float %f
119+
// CHECK-NEXT: OpSelectionMerge %if_merge_0 None
120+
// CHECK-NEXT: OpBranchConditional [[cond]] %if_true_0 %if_false_0
121+
// CHECK-NEXT: %if_true_0 = OpLabel
122+
// CHECK-NEXT: OpStore %temp_var_ternary_0 [[e]]
123+
// CHECK-NEXT: OpBranch %if_merge_0
124+
// CHECK-NEXT: %if_false_0 = OpLabel
125+
// CHECK-NEXT: OpStore %temp_var_ternary_0 [[f]]
126+
// CHECK-NEXT: OpBranch %if_merge_0
127+
// CHECK-NEXT: %if_merge_0 = OpLabel
128+
// CHECK-NEXT:[[temp:%\d+]] = OpLoad %mat2v3float %temp_var_ternary_0
129+
// CHECK-NEXT: OpStore %g [[temp]]
130+
float2x3 g = select(cond, e, f);
131+
132+
// CHECK: [[inner:%\d+]] = OpSelect %uint {{%\d+}} %uint_1 %uint_2
133+
// CHECK-NEXT: {{%\d+}} = OpSelect %uint {{%\d+}} %uint_9 [[inner]]
134+
uint h = select(cond, 9, select(cond, 1, 2));
135+
136+
//CHECK: [[i_int:%\d+]] = OpSelect %int {{%\d+}} %int_1 %int_0
137+
//CHECK-NEXT: {{%\d+}} = OpINotEqual %bool [[i_int]] %int_0
138+
bool i = select(cond, 1, 0);
139+
140+
// CHECK: [[foo:%\d+]] = OpFunctionCall %uint %foo
141+
// CHECKNEXT: {{%\d+}} = OpSelect %uint {{%\d+}} %uint_3 [[foo]]
142+
uint j = select(cond, 3, foo());
143+
144+
// CHECK: [[bar:%\d+]] = OpFunctionCall %float %bar
145+
// CHECK-NEXT: [[k_float:%\d+]] = OpSelect %float {{%\d+}} %float_4 [[bar]]
146+
// CHECK-NEXT: {{%\d+}} = OpConvertFToU %uint [[k_float]]
147+
uint k = select(cond, 4, bar());
148+
149+
zoo();
150+
151+
// CHECK: [[cond2x3:%\d+]] = OpLoad %_arr_v3bool_uint_2 %cond2x3
152+
// CHECK-NEXT: [[true2x3:%\d+]] = OpLoad %mat2v3float %true2x3
153+
// CHECK-NEXT: [[false2x3:%\d+]] = OpLoad %mat2v3float %false2x3
154+
// CHECK-NEXT: [[c0:%\d+]] = OpCompositeExtract %v3bool [[cond2x3]] 0
155+
// CHECK-NEXT: [[t0:%\d+]] = OpCompositeExtract %v3float [[true2x3]] 0
156+
// CHECK-NEXT: [[f0:%\d+]] = OpCompositeExtract %v3float [[false2x3]] 0
157+
// CHECK-NEXT: [[r0:%\d+]] = OpSelect %v3float [[c0]] [[t0]] [[f0]]
158+
// CHECK-NEXT: [[c1:%\d+]] = OpCompositeExtract %v3bool [[cond2x3]] 1
159+
// CHECK-NEXT: [[t1:%\d+]] = OpCompositeExtract %v3float [[true2x3]] 1
160+
// CHECK-NEXT: [[f1:%\d+]] = OpCompositeExtract %v3float [[false2x3]] 1
161+
// CHECK-NEXT: [[r1:%\d+]] = OpSelect %v3float [[c1]] [[t1]] [[f1]]
162+
// CHECK-NEXT: [[result:%\d+]] = OpCompositeConstruct %mat2v3float [[r0]] [[r1]]
163+
// CHECK-NEXT: OpStore %result2x3 [[result]]
164+
bool2x3 cond2x3;
165+
float2x3 true2x3, false2x3;
166+
float2x3 result2x3 = select(cond2x3, true2x3, false2x3);
167+
}
168+
169+
//
170+
// The literal integer type should be deduced from the function return type.
171+
//
172+
// CHECK: OpSelect %uint {{%\d+}} %uint_1 %uint_2
173+
uint zoo() {
174+
bool cond;
175+
return select(cond, 1, 2);
176+
}
177+

tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,7 @@ TEST_F(FileTest, IntrinsicsAllMemoryBarrier) {
12311231
TEST_F(FileTest, IntrinsicsAllMemoryBarrierWithGroupSync) {
12321232
runFileTest("intrinsics.allmemorybarrierwithgroupsync.hlsl");
12331233
}
1234+
TEST_F(FileTest, IntrinsicsAnd) { runFileTest("intrinsics.and.hlsl"); }
12341235
TEST_F(FileTest, IntrinsicsDeviceMemoryBarrierWithGroupSync) {
12351236
runFileTest("intrinsics.devicememorybarrierwithgroupsync.hlsl");
12361237
}
@@ -1291,6 +1292,7 @@ TEST_F(FileTest, IntrinsicsMsad4) { runFileTest("intrinsics.msad4.hlsl"); }
12911292
TEST_F(FileTest, IntrinsicsNormalize) {
12921293
runFileTest("intrinsics.normalize.hlsl");
12931294
}
1295+
TEST_F(FileTest, IntrinsicsOr) { runFileTest("intrinsics.or.hlsl"); }
12941296
TEST_F(FileTest, IntrinsicsPow) { runFileTest("intrinsics.pow.hlsl"); }
12951297
TEST_F(FileTest, IntrinsicsRsqrt) { runFileTest("intrinsics.rsqrt.hlsl"); }
12961298
TEST_F(FileTest, IntrinsicsFloatSign) {
@@ -1311,6 +1313,7 @@ TEST_F(FileTest, IntrinsicsSmoothStep) {
13111313
}
13121314
TEST_F(FileTest, IntrinsicsStep) { runFileTest("intrinsics.step.hlsl"); }
13131315
TEST_F(FileTest, IntrinsicsSqrt) { runFileTest("intrinsics.sqrt.hlsl"); }
1316+
TEST_F(FileTest, IntrinsicsSelect) { runFileTest("intrinsics.select.hlsl"); }
13141317
TEST_F(FileTest, IntrinsicsTranspose) {
13151318
runFileTest("intrinsics.transpose.hlsl");
13161319
}

0 commit comments

Comments
 (0)