• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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