1 // Copyright 2020 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "gmock/gmock.h"
16 #include "src/reader/spirv/function.h"
17 #include "src/reader/spirv/parser_impl_test_helper.h"
18 #include "src/reader/spirv/spirv_tools_helpers_test.h"
19
20 namespace tint {
21 namespace reader {
22 namespace spirv {
23 namespace {
24
25 using ::testing::HasSubstr;
26
Preamble()27 std::string Preamble() {
28 return R"(
29 OpCapability Shader
30 OpMemoryModel Logical Simple
31 OpEntryPoint Fragment %100 "main"
32 OpExecutionMode %100 OriginUpperLeft
33
34 %void = OpTypeVoid
35 %voidfn = OpTypeFunction %void
36
37 %bool = OpTypeBool
38 %true = OpConstantTrue %bool
39 %false = OpConstantFalse %bool
40
41 %uint = OpTypeInt 32 0
42 %int = OpTypeInt 32 1
43 %float = OpTypeFloat 32
44
45 %uint_10 = OpConstant %uint 10
46 %uint_20 = OpConstant %uint 20
47 %int_30 = OpConstant %int 30
48 %int_40 = OpConstant %int 40
49 %float_50 = OpConstant %float 50
50 %float_60 = OpConstant %float 60
51
52 %ptr_uint = OpTypePointer Function %uint
53 %ptr_int = OpTypePointer Function %int
54 %ptr_float = OpTypePointer Function %float
55
56 %v2bool = OpTypeVector %bool 2
57 %v2uint = OpTypeVector %uint 2
58 %v2int = OpTypeVector %int 2
59 %v2float = OpTypeVector %float 2
60
61 %v2bool_t_f = OpConstantComposite %v2bool %true %false
62 %v2bool_f_t = OpConstantComposite %v2bool %false %true
63 %v2uint_10_20 = OpConstantComposite %v2uint %uint_10 %uint_20
64 %v2uint_20_10 = OpConstantComposite %v2uint %uint_20 %uint_10
65 %v2int_30_40 = OpConstantComposite %v2int %int_30 %int_40
66 %v2int_40_30 = OpConstantComposite %v2int %int_40 %int_30
67 %v2float_50_60 = OpConstantComposite %v2float %float_50 %float_60
68 %v2float_60_50 = OpConstantComposite %v2float %float_60 %float_50
69 )";
70 }
71
72 // Returns the AST dump for a given SPIR-V assembly constant.
AstFor(std::string assembly)73 std::string AstFor(std::string assembly) {
74 if (assembly == "v2bool_t_f") {
75 return "vec2<bool>(true, false)";
76 }
77 if (assembly == "v2bool_f_t") {
78 return "vec2<bool>(false, true)";
79 }
80 if (assembly == "v2uint_10_20") {
81 return "vec2<u32>(10u, 20u)";
82 }
83 if (assembly == "cast_uint_10") {
84 return "bitcast<i32>(10u)";
85 }
86 if (assembly == "cast_uint_20") {
87 return "bitcast<i32>(20u)";
88 }
89 if (assembly == "cast_v2uint_10_20") {
90 return "bitcast<vec2<i32>>(vec2<u32>(10u, 20u))";
91 }
92 if (assembly == "v2uint_20_10") {
93 return "vec2<u32>(20u, 10u)";
94 }
95 if (assembly == "cast_v2uint_20_10") {
96 return "bitcast<vec2<i32>>(vec2<u32>(20u, 10u))";
97 }
98 if (assembly == "cast_int_30") {
99 return "bitcast<u32>(30)";
100 }
101 if (assembly == "cast_int_40") {
102 return "bitcast<u32>(40)";
103 }
104 if (assembly == "v2int_30_40") {
105 return "vec2<i32>(30, 40)";
106 }
107 if (assembly == "cast_v2int_30_40") {
108 return "bitcast<vec2<u32>>(vec2<i32>(30, 40))";
109 }
110 if (assembly == "v2int_40_30") {
111 return "vec2<i32>(40, 30)";
112 }
113 if (assembly == "cast_v2int_40_30") {
114 return "bitcast<vec2<u32>>(vec2<i32>(40, 30))";
115 }
116 if (assembly == "v2float_50_60") {
117 return "vec2<f32>(50.0, 60.0)";
118 }
119 if (assembly == "v2float_60_50") {
120 return "vec2<f32>(60.0, 50.0)";
121 }
122 return "bad case";
123 }
124
125 using SpvUnaryLogicalTest = SpvParserTestBase<::testing::Test>;
126
TEST_F(SpvUnaryLogicalTest,LogicalNot_Scalar)127 TEST_F(SpvUnaryLogicalTest, LogicalNot_Scalar) {
128 const auto assembly = Preamble() + R"(
129 %100 = OpFunction %void None %voidfn
130 %entry = OpLabel
131 %1 = OpLogicalNot %bool %true
132 OpReturn
133 OpFunctionEnd
134 )";
135 auto p = parser(test::Assemble(assembly));
136 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
137 auto fe = p->function_emitter(100);
138 EXPECT_TRUE(fe.EmitBody()) << p->error();
139 auto ast_body = fe.ast_body();
140 EXPECT_THAT(test::ToString(p->program(), ast_body),
141 HasSubstr("let x_1 : bool = !(true);"));
142 }
143
TEST_F(SpvUnaryLogicalTest,LogicalNot_Vector)144 TEST_F(SpvUnaryLogicalTest, LogicalNot_Vector) {
145 const auto assembly = Preamble() + R"(
146 %100 = OpFunction %void None %voidfn
147 %entry = OpLabel
148 %1 = OpLogicalNot %v2bool %v2bool_t_f
149 OpReturn
150 OpFunctionEnd
151 )";
152 auto p = parser(test::Assemble(assembly));
153 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
154 auto fe = p->function_emitter(100);
155 EXPECT_TRUE(fe.EmitBody()) << p->error();
156 auto ast_body = fe.ast_body();
157 EXPECT_THAT(test::ToString(p->program(), ast_body),
158 HasSubstr("let x_1 : vec2<bool> = !(vec2<bool>(true, false));"));
159 }
160
161 struct BinaryData {
162 const std::string res_type;
163 const std::string lhs;
164 const std::string op;
165 const std::string rhs;
166 const std::string ast_type;
167 const std::string ast_lhs;
168 const std::string ast_op;
169 const std::string ast_rhs;
170 };
operator <<(std::ostream & out,BinaryData data)171 inline std::ostream& operator<<(std::ostream& out, BinaryData data) {
172 out << "BinaryData{" << data.res_type << "," << data.lhs << "," << data.op
173 << "," << data.rhs << "," << data.ast_type << "," << data.ast_lhs << ","
174 << data.ast_op << "," << data.ast_rhs << "}";
175 return out;
176 }
177
178 using SpvBinaryLogicalTest =
179 SpvParserTestBase<::testing::TestWithParam<BinaryData>>;
180
TEST_P(SpvBinaryLogicalTest,EmitExpression)181 TEST_P(SpvBinaryLogicalTest, EmitExpression) {
182 const auto assembly = Preamble() + R"(
183 %100 = OpFunction %void None %voidfn
184 %entry = OpLabel
185 %1 = )" + GetParam().op +
186 " %" + GetParam().res_type + " %" + GetParam().lhs +
187 " %" + GetParam().rhs + R"(
188 OpReturn
189 OpFunctionEnd
190 )";
191 auto p = parser(test::Assemble(assembly));
192 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions())
193 << p->error() << "\n"
194 << assembly;
195 auto fe = p->function_emitter(100);
196 EXPECT_TRUE(fe.EmitBody()) << p->error();
197 std::ostringstream ss;
198 ss << "let x_1 : " << GetParam().ast_type << " = (" << GetParam().ast_lhs
199 << " " << GetParam().ast_op << " " << GetParam().ast_rhs << ");";
200 auto ast_body = fe.ast_body();
201 EXPECT_THAT(test::ToString(p->program(), ast_body), HasSubstr(ss.str()))
202 << assembly;
203 }
204
205 INSTANTIATE_TEST_SUITE_P(
206 SpvParserTest_IEqual,
207 SpvBinaryLogicalTest,
208 ::testing::Values(
209 // uint uint
210 BinaryData{"bool", "uint_10", "OpIEqual", "uint_20", "bool", "10u",
211 "==", "20u"},
212 // int int
213 BinaryData{"bool", "int_30", "OpIEqual", "int_40", "bool", "30",
214 "==", "40"},
215 // uint int
216 BinaryData{"bool", "uint_10", "OpIEqual", "int_40", "bool", "10u",
217 "==", "bitcast<u32>(40)"},
218 // int uint
219 BinaryData{"bool", "int_40", "OpIEqual", "uint_10", "bool", "40",
220 "==", "bitcast<i32>(10u)"},
221 // v2uint v2uint
222 BinaryData{"v2bool", "v2uint_10_20", "OpIEqual", "v2uint_20_10",
223 "vec2<bool>", AstFor("v2uint_10_20"),
224 "==", AstFor("v2uint_20_10")},
225 // v2int v2int
226 BinaryData{"v2bool", "v2int_30_40", "OpIEqual", "v2int_40_30",
227 "vec2<bool>", AstFor("v2int_30_40"),
228 "==", AstFor("v2int_40_30")}));
229
230 INSTANTIATE_TEST_SUITE_P(
231 SpvParserTest_FOrdEqual,
232 SpvBinaryLogicalTest,
233 ::testing::Values(BinaryData{"bool", "float_50", "OpFOrdEqual", "float_60",
234 "bool", "50.0", "==", "60.0"},
235 BinaryData{"v2bool", "v2float_50_60", "OpFOrdEqual",
236 "v2float_60_50", "vec2<bool>",
237 AstFor("v2float_50_60"),
238 "==", AstFor("v2float_60_50")}));
239
240 INSTANTIATE_TEST_SUITE_P(
241 SpvParserTest_INotEqual,
242 SpvBinaryLogicalTest,
243 ::testing::Values(
244 // Both uint
245 BinaryData{"bool", "uint_10", "OpINotEqual", "uint_20", "bool", "10u",
246 "!=", "20u"},
247 // Both int
248 BinaryData{"bool", "int_30", "OpINotEqual", "int_40", "bool", "30",
249 "!=", "40"},
250 // uint int
251 BinaryData{"bool", "uint_10", "OpINotEqual", "int_40", "bool", "10u",
252 "!=", "bitcast<u32>(40)"},
253 // int uint
254 BinaryData{"bool", "int_40", "OpINotEqual", "uint_10", "bool", "40",
255 "!=", "bitcast<i32>(10u)"},
256 // Both v2uint
257 BinaryData{"v2bool", "v2uint_10_20", "OpINotEqual", "v2uint_20_10",
258 "vec2<bool>", AstFor("v2uint_10_20"),
259 "!=", AstFor("v2uint_20_10")},
260 // Both v2int
261 BinaryData{"v2bool", "v2int_30_40", "OpINotEqual", "v2int_40_30",
262 "vec2<bool>", AstFor("v2int_30_40"),
263 "!=", AstFor("v2int_40_30")}));
264
265 INSTANTIATE_TEST_SUITE_P(
266 SpvParserTest_FOrdNotEqual,
267 SpvBinaryLogicalTest,
268 ::testing::Values(BinaryData{"bool", "float_50", "OpFOrdNotEqual",
269 "float_60", "bool", "50.0", "!=", "60.0"},
270 BinaryData{"v2bool", "v2float_50_60", "OpFOrdNotEqual",
271 "v2float_60_50", "vec2<bool>",
272 AstFor("v2float_50_60"),
273 "!=", AstFor("v2float_60_50")}));
274
275 INSTANTIATE_TEST_SUITE_P(
276 SpvParserTest_FOrdLessThan,
277 SpvBinaryLogicalTest,
278 ::testing::Values(BinaryData{"bool", "float_50", "OpFOrdLessThan",
279 "float_60", "bool", "50.0", "<", "60.0"},
280 BinaryData{"v2bool", "v2float_50_60", "OpFOrdLessThan",
281 "v2float_60_50", "vec2<bool>",
282 AstFor("v2float_50_60"), "<",
283 AstFor("v2float_60_50")}));
284
285 INSTANTIATE_TEST_SUITE_P(
286 SpvParserTest_FOrdLessThanEqual,
287 SpvBinaryLogicalTest,
288 ::testing::Values(BinaryData{"bool", "float_50", "OpFOrdLessThanEqual",
289 "float_60", "bool", "50.0", "<=", "60.0"},
290 BinaryData{"v2bool", "v2float_50_60",
291 "OpFOrdLessThanEqual", "v2float_60_50",
292 "vec2<bool>", AstFor("v2float_50_60"),
293 "<=", AstFor("v2float_60_50")}));
294
295 INSTANTIATE_TEST_SUITE_P(
296 SpvParserTest_FOrdGreaterThan,
297 SpvBinaryLogicalTest,
298 ::testing::Values(BinaryData{"bool", "float_50", "OpFOrdGreaterThan",
299 "float_60", "bool", "50.0", ">", "60.0"},
300 BinaryData{"v2bool", "v2float_50_60", "OpFOrdGreaterThan",
301 "v2float_60_50", "vec2<bool>",
302 AstFor("v2float_50_60"), ">",
303 AstFor("v2float_60_50")}));
304
305 INSTANTIATE_TEST_SUITE_P(
306 SpvParserTest_FOrdGreaterThanEqual,
307 SpvBinaryLogicalTest,
308 ::testing::Values(BinaryData{"bool", "float_50", "OpFOrdGreaterThanEqual",
309 "float_60", "bool", "50.0", ">=", "60.0"},
310 BinaryData{"v2bool", "v2float_50_60",
311 "OpFOrdGreaterThanEqual", "v2float_60_50",
312 "vec2<bool>", AstFor("v2float_50_60"),
313 ">=", AstFor("v2float_60_50")}));
314
315 INSTANTIATE_TEST_SUITE_P(
316 SpvParserTest_LogicalAnd,
317 SpvBinaryLogicalTest,
318 ::testing::Values(BinaryData{"bool", "true", "OpLogicalAnd", "false",
319 "bool", "true", "&", "false"},
320 BinaryData{"v2bool", "v2bool_t_f", "OpLogicalAnd",
321 "v2bool_f_t", "vec2<bool>",
322 AstFor("v2bool_t_f"), "&",
323 AstFor("v2bool_f_t")}));
324
325 INSTANTIATE_TEST_SUITE_P(
326 SpvParserTest_LogicalOr,
327 SpvBinaryLogicalTest,
328 ::testing::Values(BinaryData{"bool", "true", "OpLogicalOr", "false", "bool",
329 "true", "|", "false"},
330 BinaryData{"v2bool", "v2bool_t_f", "OpLogicalOr",
331 "v2bool_f_t", "vec2<bool>",
332 AstFor("v2bool_t_f"), "|",
333 AstFor("v2bool_f_t")}));
334
335 INSTANTIATE_TEST_SUITE_P(
336 SpvParserTest_LogicalEqual,
337 SpvBinaryLogicalTest,
338 ::testing::Values(BinaryData{"bool", "true", "OpLogicalEqual", "false",
339 "bool", "true", "==", "false"},
340 BinaryData{"v2bool", "v2bool_t_f", "OpLogicalEqual",
341 "v2bool_f_t", "vec2<bool>",
342 AstFor("v2bool_t_f"),
343 "==", AstFor("v2bool_f_t")}));
344
345 INSTANTIATE_TEST_SUITE_P(
346 SpvParserTest_LogicalNotEqual,
347 SpvBinaryLogicalTest,
348 ::testing::Values(BinaryData{"bool", "true", "OpLogicalNotEqual", "false",
349 "bool", "true", "!=", "false"},
350 BinaryData{"v2bool", "v2bool_t_f", "OpLogicalNotEqual",
351 "v2bool_f_t", "vec2<bool>",
352 AstFor("v2bool_t_f"),
353 "!=", AstFor("v2bool_f_t")}));
354
355 INSTANTIATE_TEST_SUITE_P(
356 SpvParserTest_UGreaterThan,
357 SpvBinaryLogicalTest,
358 ::testing::Values(
359 // Both unsigned
360 BinaryData{"bool", "uint_10", "OpUGreaterThan", "uint_20", "bool",
361 "10u", ">", "20u"},
362 // First arg signed
363 BinaryData{"bool", "int_30", "OpUGreaterThan", "uint_20", "bool",
364 AstFor("cast_int_30"), ">", "20u"},
365 // Second arg signed
366 BinaryData{"bool", "uint_10", "OpUGreaterThan", "int_40", "bool", "10u",
367 ">", AstFor("cast_int_40")},
368 // Vector, both unsigned
369 BinaryData{"v2bool", "v2uint_10_20", "OpUGreaterThan", "v2uint_20_10",
370 "vec2<bool>", AstFor("v2uint_10_20"), ">",
371 AstFor("v2uint_20_10")},
372 // First arg signed
373 BinaryData{"v2bool", "v2int_30_40", "OpUGreaterThan", "v2uint_20_10",
374 "vec2<bool>", AstFor("cast_v2int_30_40"), ">",
375 AstFor("v2uint_20_10")},
376 // Second arg signed
377 BinaryData{"v2bool", "v2uint_10_20", "OpUGreaterThan", "v2int_40_30",
378 "vec2<bool>", AstFor("v2uint_10_20"), ">",
379 AstFor("cast_v2int_40_30")}));
380
381 INSTANTIATE_TEST_SUITE_P(
382 SpvParserTest_UGreaterThanEqual,
383 SpvBinaryLogicalTest,
384 ::testing::Values(
385 // Both unsigned
386 BinaryData{"bool", "uint_10", "OpUGreaterThanEqual", "uint_20", "bool",
387 "10u", ">=", "20u"},
388 // First arg signed
389 BinaryData{"bool", "int_30", "OpUGreaterThanEqual", "uint_20", "bool",
390 AstFor("cast_int_30"), ">=", "20u"},
391 // Second arg signed
392 BinaryData{"bool", "uint_10", "OpUGreaterThanEqual", "int_40", "bool",
393 "10u", ">=", AstFor("cast_int_40")},
394 // Vector, both unsigned
395 BinaryData{"v2bool", "v2uint_10_20", "OpUGreaterThanEqual",
396 "v2uint_20_10", "vec2<bool>", AstFor("v2uint_10_20"),
397 ">=", AstFor("v2uint_20_10")},
398 // First arg signed
399 BinaryData{"v2bool", "v2int_30_40", "OpUGreaterThanEqual",
400 "v2uint_20_10", "vec2<bool>", AstFor("cast_v2int_30_40"),
401 ">=", AstFor("v2uint_20_10")},
402 // Second arg signed
403 BinaryData{"v2bool", "v2uint_10_20", "OpUGreaterThanEqual",
404 "v2int_40_30", "vec2<bool>", AstFor("v2uint_10_20"),
405 ">=", AstFor("cast_v2int_40_30")}));
406
407 INSTANTIATE_TEST_SUITE_P(
408 SpvParserTest_ULessThan,
409 SpvBinaryLogicalTest,
410 ::testing::Values(
411 // Both unsigned
412 BinaryData{"bool", "uint_10", "OpULessThan", "uint_20", "bool", "10u",
413 "<", "20u"},
414 // First arg signed
415 BinaryData{"bool", "int_30", "OpULessThan", "uint_20", "bool",
416 AstFor("cast_int_30"), "<", "20u"},
417 // Second arg signed
418 BinaryData{"bool", "uint_10", "OpULessThan", "int_40", "bool", "10u",
419 "<", AstFor("cast_int_40")},
420 // Vector, both unsigned
421 BinaryData{"v2bool", "v2uint_10_20", "OpULessThan", "v2uint_20_10",
422 "vec2<bool>", AstFor("v2uint_10_20"), "<",
423 AstFor("v2uint_20_10")},
424 // First arg signed
425 BinaryData{"v2bool", "v2int_30_40", "OpULessThan", "v2uint_20_10",
426 "vec2<bool>", AstFor("cast_v2int_30_40"), "<",
427 AstFor("v2uint_20_10")},
428 // Second arg signed
429 BinaryData{"v2bool", "v2uint_10_20", "OpULessThan", "v2int_40_30",
430 "vec2<bool>", AstFor("v2uint_10_20"), "<",
431 AstFor("cast_v2int_40_30")}));
432
433 INSTANTIATE_TEST_SUITE_P(
434 SpvParserTest_ULessThanEqual,
435 SpvBinaryLogicalTest,
436 ::testing::Values(
437 // Both unsigned
438 BinaryData{"bool", "uint_10", "OpULessThanEqual", "uint_20", "bool",
439 "10u", "<=", "20u"},
440 // First arg signed
441 BinaryData{"bool", "int_30", "OpULessThanEqual", "uint_20", "bool",
442 AstFor("cast_int_30"), "<=", "20u"},
443 // Second arg signed
444 BinaryData{"bool", "uint_10", "OpULessThanEqual", "int_40", "bool",
445 "10u", "<=", AstFor("cast_int_40")},
446 // Vector, both unsigned
447 BinaryData{"v2bool", "v2uint_10_20", "OpULessThanEqual", "v2uint_20_10",
448 "vec2<bool>", AstFor("v2uint_10_20"),
449 "<=", AstFor("v2uint_20_10")},
450 // First arg signed
451 BinaryData{"v2bool", "v2int_30_40", "OpULessThanEqual", "v2uint_20_10",
452 "vec2<bool>", AstFor("cast_v2int_30_40"),
453 "<=", AstFor("v2uint_20_10")},
454 // Second arg signed
455 BinaryData{"v2bool", "v2uint_10_20", "OpULessThanEqual", "v2int_40_30",
456 "vec2<bool>", AstFor("v2uint_10_20"),
457 "<=", AstFor("cast_v2int_40_30")}));
458
459 INSTANTIATE_TEST_SUITE_P(
460 SpvParserTest_SGreaterThan,
461 SpvBinaryLogicalTest,
462 ::testing::Values(
463 // Both signed
464 BinaryData{"bool", "int_30", "OpSGreaterThan", "int_40", "bool", "30",
465 ">", "40"},
466 // First arg unsigned
467 BinaryData{"bool", "uint_10", "OpSGreaterThan", "int_40", "bool",
468 AstFor("cast_uint_10"), ">", "40"},
469 // Second arg unsigned
470 BinaryData{"bool", "int_30", "OpSGreaterThan", "uint_20", "bool", "30",
471 ">", AstFor("cast_uint_20")},
472 // Vector, both signed
473 BinaryData{"v2bool", "v2int_30_40", "OpSGreaterThan", "v2int_40_30",
474 "vec2<bool>", AstFor("v2int_30_40"), ">",
475 AstFor("v2int_40_30")},
476 // First arg unsigned
477 BinaryData{"v2bool", "v2uint_10_20", "OpSGreaterThan", "v2int_40_30",
478 "vec2<bool>", AstFor("cast_v2uint_10_20"), ">",
479 AstFor("v2int_40_30")},
480 // Second arg unsigned
481 BinaryData{"v2bool", "v2int_30_40", "OpSGreaterThan", "v2uint_20_10",
482 "vec2<bool>", AstFor("v2int_30_40"), ">",
483 AstFor("cast_v2uint_20_10")}));
484
485 INSTANTIATE_TEST_SUITE_P(
486 SpvParserTest_SGreaterThanEqual,
487 SpvBinaryLogicalTest,
488 ::testing::Values(
489 // Both signed
490 BinaryData{"bool", "int_30", "OpSGreaterThanEqual", "int_40", "bool",
491 "30", ">=", "40"},
492 // First arg unsigned
493 BinaryData{"bool", "uint_10", "OpSGreaterThanEqual", "int_40", "bool",
494 AstFor("cast_uint_10"), ">=", "40"},
495 // Second arg unsigned
496 BinaryData{"bool", "int_30", "OpSGreaterThanEqual", "uint_20", "bool",
497 "30", ">=", AstFor("cast_uint_20")},
498 // Vector, both signed
499 BinaryData{"v2bool", "v2int_30_40", "OpSGreaterThanEqual",
500 "v2int_40_30", "vec2<bool>", AstFor("v2int_30_40"),
501 ">=", AstFor("v2int_40_30")},
502 // First arg unsigned
503 BinaryData{"v2bool", "v2uint_10_20", "OpSGreaterThanEqual",
504 "v2int_40_30", "vec2<bool>", AstFor("cast_v2uint_10_20"),
505 ">=", AstFor("v2int_40_30")},
506 // Second arg unsigned
507 BinaryData{"v2bool", "v2int_30_40", "OpSGreaterThanEqual",
508 "v2uint_20_10", "vec2<bool>", AstFor("v2int_30_40"),
509 ">=", AstFor("cast_v2uint_20_10")}));
510
511 INSTANTIATE_TEST_SUITE_P(
512 SpvParserTest_SLessThan,
513 SpvBinaryLogicalTest,
514 ::testing::Values(
515 // Both signed
516 BinaryData{"bool", "int_30", "OpSLessThan", "int_40", "bool", "30", "<",
517 "40"},
518 // First arg unsigned
519 BinaryData{"bool", "uint_10", "OpSLessThan", "int_40", "bool",
520 AstFor("cast_uint_10"), "<", "40"},
521 // Second arg unsigned
522 BinaryData{"bool", "int_30", "OpSLessThan", "uint_20", "bool", "30",
523 "<", AstFor("cast_uint_20")},
524 // Vector, both signed
525 BinaryData{"v2bool", "v2int_30_40", "OpSLessThan", "v2int_40_30",
526 "vec2<bool>", AstFor("v2int_30_40"), "<",
527 AstFor("v2int_40_30")},
528 // First arg unsigned
529 BinaryData{"v2bool", "v2uint_10_20", "OpSLessThan", "v2int_40_30",
530 "vec2<bool>", AstFor("cast_v2uint_10_20"), "<",
531 AstFor("v2int_40_30")},
532 // Second arg unsigned
533 BinaryData{"v2bool", "v2int_30_40", "OpSLessThan", "v2uint_20_10",
534 "vec2<bool>", AstFor("v2int_30_40"), "<",
535 AstFor("cast_v2uint_20_10")}));
536
537 INSTANTIATE_TEST_SUITE_P(
538 SpvParserTest_SLessThanEqual,
539 SpvBinaryLogicalTest,
540 ::testing::Values(
541 // Both signed
542 BinaryData{"bool", "int_30", "OpSLessThanEqual", "int_40", "bool", "30",
543 "<=", "40"},
544 // First arg unsigned
545 BinaryData{"bool", "uint_10", "OpSLessThanEqual", "int_40", "bool",
546 AstFor("cast_uint_10"), "<=", "40"},
547 // Second arg unsigned
548 BinaryData{"bool", "int_30", "OpSLessThanEqual", "uint_20", "bool",
549 "30", "<=", AstFor("cast_uint_20")},
550 // Vector, both signed
551 BinaryData{"v2bool", "v2int_30_40", "OpSLessThanEqual", "v2int_40_30",
552 "vec2<bool>", AstFor("v2int_30_40"),
553 "<=", AstFor("v2int_40_30")},
554 // First arg unsigned
555 BinaryData{"v2bool", "v2uint_10_20", "OpSLessThanEqual", "v2int_40_30",
556 "vec2<bool>", AstFor("cast_v2uint_10_20"),
557 "<=", AstFor("v2int_40_30")},
558 // Second arg unsigned
559 BinaryData{"v2bool", "v2int_30_40", "OpSLessThanEqual", "v2uint_20_10",
560 "vec2<bool>", AstFor("v2int_30_40"),
561 "<=", AstFor("cast_v2uint_20_10")}));
562
563 using SpvFUnordTest = SpvParserTestBase<::testing::Test>;
564
TEST_F(SpvFUnordTest,FUnordEqual_Scalar)565 TEST_F(SpvFUnordTest, FUnordEqual_Scalar) {
566 const auto assembly = Preamble() + R"(
567 %100 = OpFunction %void None %voidfn
568 %entry = OpLabel
569 %1 = OpFUnordEqual %bool %float_50 %float_60
570 OpReturn
571 OpFunctionEnd
572 )";
573 auto p = parser(test::Assemble(assembly));
574 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
575 auto fe = p->function_emitter(100);
576 EXPECT_TRUE(fe.EmitBody()) << p->error();
577 auto ast_body = fe.ast_body();
578 EXPECT_THAT(test::ToString(p->program(), ast_body),
579 HasSubstr("let x_1 : bool = !((50.0 != 60.0));"));
580 }
581
TEST_F(SpvFUnordTest,FUnordEqual_Vector)582 TEST_F(SpvFUnordTest, FUnordEqual_Vector) {
583 const auto assembly = Preamble() + R"(
584 %100 = OpFunction %void None %voidfn
585 %entry = OpLabel
586 %1 = OpFUnordEqual %v2bool %v2float_50_60 %v2float_60_50
587 OpReturn
588 OpFunctionEnd
589 )";
590 auto p = parser(test::Assemble(assembly));
591 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
592 auto fe = p->function_emitter(100);
593 EXPECT_TRUE(fe.EmitBody()) << p->error();
594 auto ast_body = fe.ast_body();
595 EXPECT_THAT(
596 test::ToString(p->program(), ast_body),
597 HasSubstr("let x_1 : vec2<bool> = "
598 "!((vec2<f32>(50.0, 60.0) != vec2<f32>(60.0, 50.0)));"));
599 }
600
TEST_F(SpvFUnordTest,FUnordNotEqual_Scalar)601 TEST_F(SpvFUnordTest, FUnordNotEqual_Scalar) {
602 const auto assembly = Preamble() + R"(
603 %100 = OpFunction %void None %voidfn
604 %entry = OpLabel
605 %1 = OpFUnordNotEqual %bool %float_50 %float_60
606 OpReturn
607 OpFunctionEnd
608 )";
609 auto p = parser(test::Assemble(assembly));
610 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
611 auto fe = p->function_emitter(100);
612 EXPECT_TRUE(fe.EmitBody()) << p->error();
613 auto ast_body = fe.ast_body();
614 EXPECT_THAT(test::ToString(p->program(), ast_body),
615 HasSubstr("let x_1 : bool = !((50.0 == 60.0));"));
616 }
617
TEST_F(SpvFUnordTest,FUnordNotEqual_Vector)618 TEST_F(SpvFUnordTest, FUnordNotEqual_Vector) {
619 const auto assembly = Preamble() + R"(
620 %100 = OpFunction %void None %voidfn
621 %entry = OpLabel
622 %1 = OpFUnordNotEqual %v2bool %v2float_50_60 %v2float_60_50
623 OpReturn
624 OpFunctionEnd
625 )";
626 auto p = parser(test::Assemble(assembly));
627 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
628 auto fe = p->function_emitter(100);
629 EXPECT_TRUE(fe.EmitBody()) << p->error();
630 auto ast_body = fe.ast_body();
631 EXPECT_THAT(
632 test::ToString(p->program(), ast_body),
633 HasSubstr("let x_1 : vec2<bool> = "
634 "!((vec2<f32>(50.0, 60.0) == vec2<f32>(60.0, 50.0)));"));
635 }
636
TEST_F(SpvFUnordTest,FUnordLessThan_Scalar)637 TEST_F(SpvFUnordTest, FUnordLessThan_Scalar) {
638 const auto assembly = Preamble() + R"(
639 %100 = OpFunction %void None %voidfn
640 %entry = OpLabel
641 %1 = OpFUnordLessThan %bool %float_50 %float_60
642 OpReturn
643 OpFunctionEnd
644 )";
645 auto p = parser(test::Assemble(assembly));
646 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
647 auto fe = p->function_emitter(100);
648 EXPECT_TRUE(fe.EmitBody()) << p->error();
649 auto ast_body = fe.ast_body();
650 EXPECT_THAT(test::ToString(p->program(), ast_body),
651 HasSubstr("let x_1 : bool = !((50.0 >= 60.0));"));
652 }
653
TEST_F(SpvFUnordTest,FUnordLessThan_Vector)654 TEST_F(SpvFUnordTest, FUnordLessThan_Vector) {
655 const auto assembly = Preamble() + R"(
656 %100 = OpFunction %void None %voidfn
657 %entry = OpLabel
658 %1 = OpFUnordLessThan %v2bool %v2float_50_60 %v2float_60_50
659 OpReturn
660 OpFunctionEnd
661 )";
662 auto p = parser(test::Assemble(assembly));
663 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
664 auto fe = p->function_emitter(100);
665 EXPECT_TRUE(fe.EmitBody()) << p->error();
666 auto ast_body = fe.ast_body();
667 EXPECT_THAT(
668 test::ToString(p->program(), ast_body),
669 HasSubstr("let x_1 : vec2<bool> = "
670 "!((vec2<f32>(50.0, 60.0) >= vec2<f32>(60.0, 50.0)));"));
671 }
672
TEST_F(SpvFUnordTest,FUnordLessThanEqual_Scalar)673 TEST_F(SpvFUnordTest, FUnordLessThanEqual_Scalar) {
674 const auto assembly = Preamble() + R"(
675 %100 = OpFunction %void None %voidfn
676 %entry = OpLabel
677 %1 = OpFUnordLessThanEqual %bool %float_50 %float_60
678 OpReturn
679 OpFunctionEnd
680 )";
681 auto p = parser(test::Assemble(assembly));
682 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
683 auto fe = p->function_emitter(100);
684 EXPECT_TRUE(fe.EmitBody()) << p->error();
685 auto ast_body = fe.ast_body();
686 EXPECT_THAT(test::ToString(p->program(), ast_body),
687 HasSubstr("let x_1 : bool = !((50.0 > 60.0));"));
688 }
689
TEST_F(SpvFUnordTest,FUnordLessThanEqual_Vector)690 TEST_F(SpvFUnordTest, FUnordLessThanEqual_Vector) {
691 const auto assembly = Preamble() + R"(
692 %100 = OpFunction %void None %voidfn
693 %entry = OpLabel
694 %1 = OpFUnordLessThanEqual %v2bool %v2float_50_60 %v2float_60_50
695 OpReturn
696 OpFunctionEnd
697 )";
698 auto p = parser(test::Assemble(assembly));
699 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
700 auto fe = p->function_emitter(100);
701 EXPECT_TRUE(fe.EmitBody()) << p->error();
702 auto ast_body = fe.ast_body();
703 EXPECT_THAT(test::ToString(p->program(), ast_body),
704 HasSubstr("let x_1 : vec2<bool> = "
705 "!((vec2<f32>(50.0, 60.0) > vec2<f32>(60.0, 50.0)));"));
706 }
707
TEST_F(SpvFUnordTest,FUnordGreaterThan_Scalar)708 TEST_F(SpvFUnordTest, FUnordGreaterThan_Scalar) {
709 const auto assembly = Preamble() + R"(
710 %100 = OpFunction %void None %voidfn
711 %entry = OpLabel
712 %1 = OpFUnordGreaterThan %bool %float_50 %float_60
713 OpReturn
714 OpFunctionEnd
715 )";
716 auto p = parser(test::Assemble(assembly));
717 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
718 auto fe = p->function_emitter(100);
719 EXPECT_TRUE(fe.EmitBody()) << p->error();
720 auto ast_body = fe.ast_body();
721 EXPECT_THAT(test::ToString(p->program(), ast_body),
722 HasSubstr("let x_1 : bool = !((50.0 <= 60.0));"));
723 }
724
TEST_F(SpvFUnordTest,FUnordGreaterThan_Vector)725 TEST_F(SpvFUnordTest, FUnordGreaterThan_Vector) {
726 const auto assembly = Preamble() + R"(
727 %100 = OpFunction %void None %voidfn
728 %entry = OpLabel
729 %1 = OpFUnordGreaterThan %v2bool %v2float_50_60 %v2float_60_50
730 OpReturn
731 OpFunctionEnd
732 )";
733 auto p = parser(test::Assemble(assembly));
734 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
735 auto fe = p->function_emitter(100);
736 EXPECT_TRUE(fe.EmitBody()) << p->error();
737 auto ast_body = fe.ast_body();
738 EXPECT_THAT(
739 test::ToString(p->program(), ast_body),
740 HasSubstr("let x_1 : vec2<bool> = "
741 "!((vec2<f32>(50.0, 60.0) <= vec2<f32>(60.0, 50.0)));"));
742 }
743
TEST_F(SpvFUnordTest,FUnordGreaterThanEqual_Scalar)744 TEST_F(SpvFUnordTest, FUnordGreaterThanEqual_Scalar) {
745 const auto assembly = Preamble() + R"(
746 %100 = OpFunction %void None %voidfn
747 %entry = OpLabel
748 %1 = OpFUnordGreaterThanEqual %bool %float_50 %float_60
749 OpReturn
750 OpFunctionEnd
751 )";
752 auto p = parser(test::Assemble(assembly));
753 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
754 auto fe = p->function_emitter(100);
755 EXPECT_TRUE(fe.EmitBody()) << p->error();
756 auto ast_body = fe.ast_body();
757 EXPECT_THAT(test::ToString(p->program(), ast_body),
758 HasSubstr("let x_1 : bool = !((50.0 < 60.0));"));
759 }
760
TEST_F(SpvFUnordTest,FUnordGreaterThanEqual_Vector)761 TEST_F(SpvFUnordTest, FUnordGreaterThanEqual_Vector) {
762 const auto assembly = Preamble() + R"(
763 %100 = OpFunction %void None %voidfn
764 %entry = OpLabel
765 %1 = OpFUnordGreaterThanEqual %v2bool %v2float_50_60 %v2float_60_50
766 OpReturn
767 OpFunctionEnd
768 )";
769 auto p = parser(test::Assemble(assembly));
770 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
771 auto fe = p->function_emitter(100);
772 EXPECT_TRUE(fe.EmitBody()) << p->error();
773 auto ast_body = fe.ast_body();
774 EXPECT_THAT(test::ToString(p->program(), ast_body),
775 HasSubstr("let x_1 : vec2<bool> = !(("
776 "vec2<f32>(50.0, 60.0) < vec2<f32>(60.0, 50.0)"
777 "));"));
778 }
779
780 using SpvLogicalTest = SpvParserTestBase<::testing::Test>;
781
TEST_F(SpvLogicalTest,Select_BoolCond_BoolParams)782 TEST_F(SpvLogicalTest, Select_BoolCond_BoolParams) {
783 const auto assembly = Preamble() + R"(
784 %100 = OpFunction %void None %voidfn
785 %entry = OpLabel
786 %1 = OpSelect %bool %true %true %false
787 OpReturn
788 OpFunctionEnd
789 )";
790 auto p = parser(test::Assemble(assembly));
791 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
792 auto fe = p->function_emitter(100);
793 EXPECT_TRUE(fe.EmitBody()) << p->error();
794 auto ast_body = fe.ast_body();
795 EXPECT_THAT(test::ToString(p->program(), ast_body),
796 HasSubstr("let x_1 : bool = select(false, true, true);"));
797 }
798
TEST_F(SpvLogicalTest,Select_BoolCond_IntScalarParams)799 TEST_F(SpvLogicalTest, Select_BoolCond_IntScalarParams) {
800 const auto assembly = Preamble() + R"(
801 %100 = OpFunction %void None %voidfn
802 %entry = OpLabel
803 %1 = OpSelect %uint %true %uint_10 %uint_20
804 OpReturn
805 OpFunctionEnd
806 )";
807 auto p = parser(test::Assemble(assembly));
808 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
809 auto fe = p->function_emitter(100);
810 EXPECT_TRUE(fe.EmitBody()) << p->error();
811 auto ast_body = fe.ast_body();
812 EXPECT_THAT(test::ToString(p->program(), ast_body),
813 HasSubstr("let x_1 : u32 = select(20u, 10u, true);"));
814 }
815
TEST_F(SpvLogicalTest,Select_BoolCond_FloatScalarParams)816 TEST_F(SpvLogicalTest, Select_BoolCond_FloatScalarParams) {
817 const auto assembly = Preamble() + R"(
818 %100 = OpFunction %void None %voidfn
819 %entry = OpLabel
820 %1 = OpSelect %float %true %float_50 %float_60
821 OpReturn
822 OpFunctionEnd
823 )";
824 auto p = parser(test::Assemble(assembly));
825 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
826 auto fe = p->function_emitter(100);
827 EXPECT_TRUE(fe.EmitBody()) << p->error();
828 auto ast_body = fe.ast_body();
829 EXPECT_THAT(test::ToString(p->program(), ast_body),
830 HasSubstr("let x_1 : f32 = select(60.0, 50.0, true);"));
831 }
832
TEST_F(SpvLogicalTest,Select_BoolCond_VectorParams)833 TEST_F(SpvLogicalTest, Select_BoolCond_VectorParams) {
834 // Prior to SPIR-V 1.4, the condition must be a vector of bools
835 // when the value operands are vectors.
836 // "Before version 1.4, results are only computed per component."
837 const auto assembly = Preamble() + R"(
838 %100 = OpFunction %void None %voidfn
839 %entry = OpLabel
840 %1 = OpSelect %v2uint %true %v2uint_10_20 %v2uint_20_10
841 OpReturn
842 OpFunctionEnd
843 )";
844 auto p = parser(test::Assemble(assembly));
845 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
846 auto fe = p->function_emitter(100);
847 EXPECT_TRUE(fe.EmitBody()) << p->error();
848 auto ast_body = fe.ast_body();
849 EXPECT_THAT(test::ToString(p->program(), ast_body),
850 HasSubstr("let x_1 : vec2<u32> = select("
851 "vec2<u32>(20u, 10u), "
852 "vec2<u32>(10u, 20u), "
853 "true);"));
854
855 // Fails validation prior to SPIR-V 1.4: If the value operands are vectors,
856 // then the condition must be a vector.
857 // "Expected vector sizes of Result Type and the condition to be equal:
858 // Select"
859 p->DeliberatelyInvalidSpirv();
860 }
861
TEST_F(SpvLogicalTest,Select_VecBoolCond_VectorParams)862 TEST_F(SpvLogicalTest, Select_VecBoolCond_VectorParams) {
863 const auto assembly = Preamble() + R"(
864 %100 = OpFunction %void None %voidfn
865 %entry = OpLabel
866 %1 = OpSelect %v2uint %v2bool_t_f %v2uint_10_20 %v2uint_20_10
867 OpReturn
868 OpFunctionEnd
869 )";
870 auto p = parser(test::Assemble(assembly));
871 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
872 auto fe = p->function_emitter(100);
873 EXPECT_TRUE(fe.EmitBody()) << p->error();
874 auto ast_body = fe.ast_body();
875 EXPECT_THAT(test::ToString(p->program(), ast_body),
876 HasSubstr("let x_1 : vec2<u32> = select("
877 "vec2<u32>(20u, 10u), "
878 "vec2<u32>(10u, 20u), "
879 "vec2<bool>(true, false));"));
880 }
881
TEST_F(SpvLogicalTest,Any)882 TEST_F(SpvLogicalTest, Any) {
883 const auto assembly = Preamble() + R"(
884 %100 = OpFunction %void None %voidfn
885 %entry = OpLabel
886 %1 = OpAny %bool %v2bool_t_f
887 OpReturn
888 OpFunctionEnd
889 )";
890 auto p = parser(test::Assemble(assembly));
891 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
892 auto fe = p->function_emitter(100);
893 EXPECT_TRUE(fe.EmitBody()) << p->error();
894 auto ast_body = fe.ast_body();
895 EXPECT_THAT(test::ToString(p->program(), ast_body),
896 HasSubstr("let x_1 : bool = any(vec2<bool>(true, false));"));
897 }
898
TEST_F(SpvLogicalTest,All)899 TEST_F(SpvLogicalTest, All) {
900 const auto assembly = Preamble() + R"(
901 %100 = OpFunction %void None %voidfn
902 %entry = OpLabel
903 %1 = OpAll %bool %v2bool_t_f
904 OpReturn
905 OpFunctionEnd
906 )";
907 auto p = parser(test::Assemble(assembly));
908 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
909 auto fe = p->function_emitter(100);
910 EXPECT_TRUE(fe.EmitBody()) << p->error();
911 auto ast_body = fe.ast_body();
912 EXPECT_THAT(test::ToString(p->program(), ast_body),
913 HasSubstr("let x_1 : bool = all(vec2<bool>(true, false));"));
914 }
915
TEST_F(SpvLogicalTest,IsNan_Scalar)916 TEST_F(SpvLogicalTest, IsNan_Scalar) {
917 const auto assembly = Preamble() + R"(
918 %100 = OpFunction %void None %voidfn
919 %entry = OpLabel
920 %1 = OpIsNan %bool %float_50
921 OpReturn
922 OpFunctionEnd
923 )";
924 auto p = parser(test::Assemble(assembly));
925 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
926 auto fe = p->function_emitter(100);
927 EXPECT_TRUE(fe.EmitBody()) << p->error();
928 auto ast_body = fe.ast_body();
929 EXPECT_THAT(test::ToString(p->program(), ast_body),
930 HasSubstr("let x_1 : bool = isNan(50.0);"));
931 }
932
TEST_F(SpvLogicalTest,IsNan_Vector)933 TEST_F(SpvLogicalTest, IsNan_Vector) {
934 const auto assembly = Preamble() + R"(
935 %100 = OpFunction %void None %voidfn
936 %entry = OpLabel
937 %1 = OpIsNan %v2bool %v2float_50_60
938 OpReturn
939 OpFunctionEnd
940 )";
941 auto p = parser(test::Assemble(assembly));
942 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
943 auto fe = p->function_emitter(100);
944 EXPECT_TRUE(fe.EmitBody()) << p->error();
945 auto ast_body = fe.ast_body();
946 EXPECT_THAT(
947 test::ToString(p->program(), ast_body),
948 HasSubstr("let x_1 : vec2<bool> = isNan(vec2<f32>(50.0, 60.0));"));
949 }
950
TEST_F(SpvLogicalTest,IsInf_Scalar)951 TEST_F(SpvLogicalTest, IsInf_Scalar) {
952 const auto assembly = Preamble() + R"(
953 %100 = OpFunction %void None %voidfn
954 %entry = OpLabel
955 %1 = OpIsInf %bool %float_50
956 OpReturn
957 OpFunctionEnd
958 )";
959 auto p = parser(test::Assemble(assembly));
960 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
961 auto fe = p->function_emitter(100);
962 EXPECT_TRUE(fe.EmitBody()) << p->error();
963 auto ast_body = fe.ast_body();
964 EXPECT_THAT(test::ToString(p->program(), ast_body),
965 HasSubstr("let x_1 : bool = isInf(50.0);"));
966 }
967
TEST_F(SpvLogicalTest,IsInf_Vector)968 TEST_F(SpvLogicalTest, IsInf_Vector) {
969 const auto assembly = Preamble() + R"(
970 %100 = OpFunction %void None %voidfn
971 %entry = OpLabel
972 %1 = OpIsInf %v2bool %v2float_50_60
973 OpReturn
974 OpFunctionEnd
975 )";
976 auto p = parser(test::Assemble(assembly));
977 ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions());
978 auto fe = p->function_emitter(100);
979 EXPECT_TRUE(fe.EmitBody()) << p->error();
980 auto ast_body = fe.ast_body();
981 EXPECT_THAT(
982 test::ToString(p->program(), ast_body),
983 HasSubstr("let x_1 : vec2<bool> = isInf(vec2<f32>(50.0, 60.0));"));
984 }
985
986 // TODO(dneto): Kernel-guarded instructions.
987 // TODO(dneto): OpSelect over more general types, as in SPIR-V 1.4
988
989 } // namespace
990 } // namespace spirv
991 } // namespace reader
992 } // namespace tint
993