1 // Copyright (c) 2016 Google Inc.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 #include "source/opt/fold.h"
15
16 #include <limits>
17 #include <memory>
18 #include <string>
19 #include <unordered_set>
20 #include <vector>
21
22 #include "effcee/effcee.h"
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "source/opt/build_module.h"
26 #include "source/opt/def_use_manager.h"
27 #include "source/opt/ir_context.h"
28 #include "source/opt/module.h"
29 #include "spirv-tools/libspirv.hpp"
30 #include "test/opt/pass_utils.h"
31
32 namespace spvtools {
33 namespace opt {
34 namespace {
35
36 using ::testing::Contains;
37
Disassemble(const std::string & original,IRContext * context,uint32_t disassemble_options=0)38 std::string Disassemble(const std::string& original, IRContext* context,
39 uint32_t disassemble_options = 0) {
40 std::vector<uint32_t> optimized_bin;
41 context->module()->ToBinary(&optimized_bin, true);
42 spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
43 SpirvTools tools(target_env);
44 std::string optimized_asm;
45 EXPECT_TRUE(
46 tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options))
47 << "Disassembling failed for shader:\n"
48 << original << std::endl;
49 return optimized_asm;
50 }
51
Match(const std::string & original,IRContext * context,uint32_t disassemble_options=0)52 void Match(const std::string& original, IRContext* context,
53 uint32_t disassemble_options = 0) {
54 std::string disassembly = Disassemble(original, context, disassemble_options);
55 auto match_result = effcee::Match(disassembly, original);
56 EXPECT_EQ(effcee::Result::Status::Ok, match_result.status())
57 << match_result.message() << "\nChecking result:\n"
58 << disassembly;
59 }
60
61 template <class ResultType>
62 struct InstructionFoldingCase {
InstructionFoldingCasespvtools::opt::__anona22e47290111::InstructionFoldingCase63 InstructionFoldingCase(const std::string& tb, uint32_t id, ResultType result)
64 : test_body(tb), id_to_fold(id), expected_result(result) {}
65
66 std::string test_body;
67 uint32_t id_to_fold;
68 ResultType expected_result;
69 };
70
71 using IntegerInstructionFoldingTest =
72 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
73
TEST_P(IntegerInstructionFoldingTest,Case)74 TEST_P(IntegerInstructionFoldingTest, Case) {
75 const auto& tc = GetParam();
76
77 // Build module.
78 std::unique_ptr<IRContext> context =
79 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
80 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
81 ASSERT_NE(nullptr, context);
82
83 // Fold the instruction to test.
84 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
85 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
86 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
87
88 // Make sure the instruction folded as expected.
89 EXPECT_TRUE(succeeded);
90 if (inst != nullptr) {
91 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
92 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
93 EXPECT_EQ(inst->opcode(), SpvOpConstant);
94 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
95 const analysis::IntConstant* result =
96 const_mrg->GetConstantFromInst(inst)->AsIntConstant();
97 EXPECT_NE(result, nullptr);
98 if (result != nullptr) {
99 EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
100 }
101 }
102 }
103
104 // Returns a common SPIR-V header for all of the test that follow.
105 #define INT_0_ID 100
106 #define TRUE_ID 101
107 #define VEC2_0_ID 102
108 #define INT_7_ID 103
109 #define FLOAT_0_ID 104
110 #define DOUBLE_0_ID 105
111 #define VEC4_0_ID 106
112 #define DVEC4_0_ID 106
113 #define HALF_0_ID 108
Header()114 const std::string& Header() {
115 static const std::string header = R"(OpCapability Shader
116 OpCapability Float16
117 OpCapability Float64
118 OpCapability Int16
119 OpCapability Int64
120 %1 = OpExtInstImport "GLSL.std.450"
121 OpMemoryModel Logical GLSL450
122 OpEntryPoint Fragment %main "main"
123 OpExecutionMode %main OriginUpperLeft
124 OpSource GLSL 140
125 OpName %main "main"
126 %void = OpTypeVoid
127 %void_func = OpTypeFunction %void
128 %bool = OpTypeBool
129 %float = OpTypeFloat 32
130 %double = OpTypeFloat 64
131 %half = OpTypeFloat 16
132 %101 = OpConstantTrue %bool ; Need a def with an numerical id to define id maps.
133 %true = OpConstantTrue %bool
134 %false = OpConstantFalse %bool
135 %bool_null = OpConstantNull %bool
136 %short = OpTypeInt 16 1
137 %int = OpTypeInt 32 1
138 %long = OpTypeInt 64 1
139 %uint = OpTypeInt 32 0
140 %v2int = OpTypeVector %int 2
141 %v4int = OpTypeVector %int 4
142 %v4float = OpTypeVector %float 4
143 %v4double = OpTypeVector %double 4
144 %v2float = OpTypeVector %float 2
145 %v2double = OpTypeVector %double 2
146 %v2half = OpTypeVector %half 2
147 %v2bool = OpTypeVector %bool 2
148 %struct_v2int_int_int = OpTypeStruct %v2int %int %int
149 %_ptr_int = OpTypePointer Function %int
150 %_ptr_uint = OpTypePointer Function %uint
151 %_ptr_bool = OpTypePointer Function %bool
152 %_ptr_float = OpTypePointer Function %float
153 %_ptr_double = OpTypePointer Function %double
154 %_ptr_half = OpTypePointer Function %half
155 %_ptr_long = OpTypePointer Function %long
156 %_ptr_v2int = OpTypePointer Function %v2int
157 %_ptr_v4int = OpTypePointer Function %v4int
158 %_ptr_v4float = OpTypePointer Function %v4float
159 %_ptr_v4double = OpTypePointer Function %v4double
160 %_ptr_struct_v2int_int_int = OpTypePointer Function %struct_v2int_int_int
161 %_ptr_v2float = OpTypePointer Function %v2float
162 %_ptr_v2double = OpTypePointer Function %v2double
163 %short_0 = OpConstant %short 0
164 %short_2 = OpConstant %short 2
165 %short_3 = OpConstant %short 3
166 %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps.
167 %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps.
168 %int_0 = OpConstant %int 0
169 %int_1 = OpConstant %int 1
170 %int_2 = OpConstant %int 2
171 %int_3 = OpConstant %int 3
172 %int_4 = OpConstant %int 4
173 %int_n24 = OpConstant %int -24
174 %int_min = OpConstant %int -2147483648
175 %int_max = OpConstant %int 2147483647
176 %long_0 = OpConstant %long 0
177 %long_2 = OpConstant %long 2
178 %long_3 = OpConstant %long 3
179 %uint_0 = OpConstant %uint 0
180 %uint_1 = OpConstant %uint 1
181 %uint_2 = OpConstant %uint 2
182 %uint_3 = OpConstant %uint 3
183 %uint_4 = OpConstant %uint 4
184 %uint_32 = OpConstant %uint 32
185 %uint_42 = OpConstant %uint 42
186 %uint_max = OpConstant %uint 4294967295
187 %v2int_undef = OpUndef %v2int
188 %v2int_0_0 = OpConstantComposite %v2int %int_0 %int_0
189 %v2int_1_0 = OpConstantComposite %v2int %int_1 %int_0
190 %v2int_2_2 = OpConstantComposite %v2int %int_2 %int_2
191 %v2int_2_3 = OpConstantComposite %v2int %int_2 %int_3
192 %v2int_3_2 = OpConstantComposite %v2int %int_3 %int_2
193 %v2int_4_4 = OpConstantComposite %v2int %int_4 %int_4
194 %v2bool_null = OpConstantNull %v2bool
195 %v2bool_true_false = OpConstantComposite %v2bool %true %false
196 %v2bool_false_true = OpConstantComposite %v2bool %false %true
197 %struct_v2int_int_int_null = OpConstantNull %struct_v2int_int_int
198 %v2int_null = OpConstantNull %v2int
199 %102 = OpConstantComposite %v2int %103 %103
200 %v4int_0_0_0_0 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
201 %struct_undef_0_0 = OpConstantComposite %struct_v2int_int_int %v2int_undef %int_0 %int_0
202 %float_n1 = OpConstant %float -1
203 %104 = OpConstant %float 0 ; Need a def with an numerical id to define id maps.
204 %float_null = OpConstantNull %float
205 %float_0 = OpConstant %float 0
206 %float_1 = OpConstant %float 1
207 %float_2 = OpConstant %float 2
208 %float_3 = OpConstant %float 3
209 %float_4 = OpConstant %float 4
210 %float_2049 = OpConstant %float 2049
211 %float_n2049 = OpConstant %float -2049
212 %float_0p5 = OpConstant %float 0.5
213 %float_0p2 = OpConstant %float 0.2
214 %float_pi = OpConstant %float 1.5555
215 %float_1e16 = OpConstant %float 1e16
216 %float_n1e16 = OpConstant %float -1e16
217 %float_1en16 = OpConstant %float 1e-16
218 %float_n1en16 = OpConstant %float -1e-16
219 %v2float_0_0 = OpConstantComposite %v2float %float_0 %float_0
220 %v2float_2_2 = OpConstantComposite %v2float %float_2 %float_2
221 %v2float_2_3 = OpConstantComposite %v2float %float_2 %float_3
222 %v2float_3_2 = OpConstantComposite %v2float %float_3 %float_2
223 %v2float_4_4 = OpConstantComposite %v2float %float_4 %float_4
224 %v2float_2_0p5 = OpConstantComposite %v2float %float_2 %float_0p5
225 %v2float_0p2_0p5 = OpConstantComposite %v2float %float_0p2 %float_0p5
226 %v2float_null = OpConstantNull %v2float
227 %double_n1 = OpConstant %double -1
228 %105 = OpConstant %double 0 ; Need a def with an numerical id to define id maps.
229 %double_null = OpConstantNull %double
230 %double_0 = OpConstant %double 0
231 %double_1 = OpConstant %double 1
232 %double_2 = OpConstant %double 2
233 %double_3 = OpConstant %double 3
234 %double_4 = OpConstant %double 4
235 %double_5 = OpConstant %double 5
236 %double_0p5 = OpConstant %double 0.5
237 %double_0p2 = OpConstant %double 0.2
238 %v2double_0_0 = OpConstantComposite %v2double %double_0 %double_0
239 %v2double_2_2 = OpConstantComposite %v2double %double_2 %double_2
240 %v2double_2_3 = OpConstantComposite %v2double %double_2 %double_3
241 %v2double_3_2 = OpConstantComposite %v2double %double_3 %double_2
242 %v2double_4_4 = OpConstantComposite %v2double %double_4 %double_4
243 %v2double_2_0p5 = OpConstantComposite %v2double %double_2 %double_0p5
244 %v2double_null = OpConstantNull %v2double
245 %108 = OpConstant %half 0
246 %half_1 = OpConstant %half 1
247 %half_0_1 = OpConstantComposite %v2half %108 %half_1
248 %106 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
249 %v4float_0_0_0_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
250 %v4float_0_0_0_1 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
251 %v4float_0_1_0_0 = OpConstantComposite %v4float %float_0 %float_1 %float_null %float_0
252 %v4float_1_1_1_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
253 %107 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
254 %v4double_0_0_0_0 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
255 %v4double_0_0_0_1 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_1
256 %v4double_0_1_0_0 = OpConstantComposite %v4double %double_0 %double_1 %double_null %double_0
257 %v4double_1_1_1_1 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_1
258 %v4double_1_1_1_0p5 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_0p5
259 %v4double_null = OpConstantNull %v4double
260 %v4float_n1_2_1_3 = OpConstantComposite %v4float %float_n1 %float_2 %float_1 %float_3
261 )";
262
263 return header;
264 }
265
266 // Returns the header with definitions of float NaN and double NaN. Since FC
267 // "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" finds
268 // %double_nan = OpConstant %double -0x1.8p+1024 instead of
269 // %double_n0 = OpConstant %double -0,
270 // we separates those definitions from Header().
HeaderWithNaN()271 const std::string& HeaderWithNaN() {
272 static const std::string headerWithNaN =
273 Header() +
274 R"(%float_nan = OpConstant %float -0x1.8p+128
275 %double_nan = OpConstant %double -0x1.8p+1024
276 )";
277
278 return headerWithNaN;
279 }
280
281 // clang-format off
282 INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTest,
283 ::testing::Values(
284 // Test case 0: fold 0*n
285 InstructionFoldingCase<uint32_t>(
286 Header() + "%main = OpFunction %void None %void_func\n" +
287 "%main_lab = OpLabel\n" +
288 "%n = OpVariable %_ptr_int Function\n" +
289 "%load = OpLoad %int %n\n" +
290 "%2 = OpIMul %int %int_0 %load\n" +
291 "OpReturn\n" +
292 "OpFunctionEnd",
293 2, 0),
294 // Test case 1: fold n*0
295 InstructionFoldingCase<uint32_t>(
296 Header() + "%main = OpFunction %void None %void_func\n" +
297 "%main_lab = OpLabel\n" +
298 "%n = OpVariable %_ptr_int Function\n" +
299 "%load = OpLoad %int %n\n" +
300 "%2 = OpIMul %int %load %int_0\n" +
301 "OpReturn\n" +
302 "OpFunctionEnd",
303 2, 0),
304 // Test case 2: fold 0/n (signed)
305 InstructionFoldingCase<uint32_t>(
306 Header() + "%main = OpFunction %void None %void_func\n" +
307 "%main_lab = OpLabel\n" +
308 "%n = OpVariable %_ptr_int Function\n" +
309 "%load = OpLoad %int %n\n" +
310 "%2 = OpSDiv %int %int_0 %load\n" +
311 "OpReturn\n" +
312 "OpFunctionEnd",
313 2, 0),
314 // Test case 3: fold n/0 (signed)
315 InstructionFoldingCase<uint32_t>(
316 Header() + "%main = OpFunction %void None %void_func\n" +
317 "%main_lab = OpLabel\n" +
318 "%n = OpVariable %_ptr_int Function\n" +
319 "%load = OpLoad %int %n\n" +
320 "%2 = OpSDiv %int %load %int_0\n" +
321 "OpReturn\n" +
322 "OpFunctionEnd",
323 2, 0),
324 // Test case 4: fold 0/n (unsigned)
325 InstructionFoldingCase<uint32_t>(
326 Header() + "%main = OpFunction %void None %void_func\n" +
327 "%main_lab = OpLabel\n" +
328 "%n = OpVariable %_ptr_uint Function\n" +
329 "%load = OpLoad %uint %n\n" +
330 "%2 = OpUDiv %uint %uint_0 %load\n" +
331 "OpReturn\n" +
332 "OpFunctionEnd",
333 2, 0),
334 // Test case 5: fold n/0 (unsigned)
335 InstructionFoldingCase<uint32_t>(
336 Header() + "%main = OpFunction %void None %void_func\n" +
337 "%main_lab = OpLabel\n" +
338 "%n = OpVariable %_ptr_int Function\n" +
339 "%load = OpLoad %int %n\n" +
340 "%2 = OpSDiv %int %load %int_0\n" +
341 "OpReturn\n" +
342 "OpFunctionEnd",
343 2, 0),
344 // Test case 6: fold 0 remainder n
345 InstructionFoldingCase<uint32_t>(
346 Header() + "%main = OpFunction %void None %void_func\n" +
347 "%main_lab = OpLabel\n" +
348 "%n = OpVariable %_ptr_int Function\n" +
349 "%load = OpLoad %int %n\n" +
350 "%2 = OpSRem %int %int_0 %load\n" +
351 "OpReturn\n" +
352 "OpFunctionEnd",
353 2, 0),
354 // Test case 7: fold n remainder 0
355 InstructionFoldingCase<uint32_t>(
356 Header() + "%main = OpFunction %void None %void_func\n" +
357 "%main_lab = OpLabel\n" +
358 "%n = OpVariable %_ptr_int Function\n" +
359 "%load = OpLoad %int %n\n" +
360 "%2 = OpSRem %int %load %int_0\n" +
361 "OpReturn\n" +
362 "OpFunctionEnd",
363 2, 0),
364 // Test case 8: fold 0%n (signed)
365 InstructionFoldingCase<uint32_t>(
366 Header() + "%main = OpFunction %void None %void_func\n" +
367 "%main_lab = OpLabel\n" +
368 "%n = OpVariable %_ptr_int Function\n" +
369 "%load = OpLoad %int %n\n" +
370 "%2 = OpSMod %int %int_0 %load\n" +
371 "OpReturn\n" +
372 "OpFunctionEnd",
373 2, 0),
374 // Test case 9: fold n%0 (signed)
375 InstructionFoldingCase<uint32_t>(
376 Header() + "%main = OpFunction %void None %void_func\n" +
377 "%main_lab = OpLabel\n" +
378 "%n = OpVariable %_ptr_int Function\n" +
379 "%load = OpLoad %int %n\n" +
380 "%2 = OpSMod %int %load %int_0\n" +
381 "OpReturn\n" +
382 "OpFunctionEnd",
383 2, 0),
384 // Test case 10: fold 0%n (unsigned)
385 InstructionFoldingCase<uint32_t>(
386 Header() + "%main = OpFunction %void None %void_func\n" +
387 "%main_lab = OpLabel\n" +
388 "%n = OpVariable %_ptr_uint Function\n" +
389 "%load = OpLoad %uint %n\n" +
390 "%2 = OpUMod %uint %uint_0 %load\n" +
391 "OpReturn\n" +
392 "OpFunctionEnd",
393 2, 0),
394 // Test case 11: fold n%0 (unsigned)
395 InstructionFoldingCase<uint32_t>(
396 Header() + "%main = OpFunction %void None %void_func\n" +
397 "%main_lab = OpLabel\n" +
398 "%n = OpVariable %_ptr_uint Function\n" +
399 "%load = OpLoad %uint %n\n" +
400 "%2 = OpUMod %uint %load %uint_0\n" +
401 "OpReturn\n" +
402 "OpFunctionEnd",
403 2, 0),
404 // Test case 12: fold n << 32
405 InstructionFoldingCase<uint32_t>(
406 Header() + "%main = OpFunction %void None %void_func\n" +
407 "%main_lab = OpLabel\n" +
408 "%n = OpVariable %_ptr_uint Function\n" +
409 "%load = OpLoad %uint %n\n" +
410 "%2 = OpShiftLeftLogical %uint %load %uint_32\n" +
411 "OpReturn\n" +
412 "OpFunctionEnd",
413 2, 0),
414 // Test case 13: fold n >> 32
415 InstructionFoldingCase<uint32_t>(
416 Header() + "%main = OpFunction %void None %void_func\n" +
417 "%main_lab = OpLabel\n" +
418 "%n = OpVariable %_ptr_uint Function\n" +
419 "%load = OpLoad %uint %n\n" +
420 "%2 = OpShiftRightLogical %uint %load %uint_32\n" +
421 "OpReturn\n" +
422 "OpFunctionEnd",
423 2, 0),
424 // Test case 14: fold n | 0xFFFFFFFF
425 InstructionFoldingCase<uint32_t>(
426 Header() + "%main = OpFunction %void None %void_func\n" +
427 "%main_lab = OpLabel\n" +
428 "%n = OpVariable %_ptr_uint Function\n" +
429 "%load = OpLoad %uint %n\n" +
430 "%2 = OpBitwiseOr %uint %load %uint_max\n" +
431 "OpReturn\n" +
432 "OpFunctionEnd",
433 2, 0xFFFFFFFF),
434 // Test case 15: fold 0xFFFFFFFF | n
435 InstructionFoldingCase<uint32_t>(
436 Header() + "%main = OpFunction %void None %void_func\n" +
437 "%main_lab = OpLabel\n" +
438 "%n = OpVariable %_ptr_uint Function\n" +
439 "%load = OpLoad %uint %n\n" +
440 "%2 = OpBitwiseOr %uint %uint_max %load\n" +
441 "OpReturn\n" +
442 "OpFunctionEnd",
443 2, 0xFFFFFFFF),
444 // Test case 16: fold n & 0
445 InstructionFoldingCase<uint32_t>(
446 Header() + "%main = OpFunction %void None %void_func\n" +
447 "%main_lab = OpLabel\n" +
448 "%n = OpVariable %_ptr_uint Function\n" +
449 "%load = OpLoad %uint %n\n" +
450 "%2 = OpBitwiseAnd %uint %load %uint_0\n" +
451 "OpReturn\n" +
452 "OpFunctionEnd",
453 2, 0),
454 // Test case 17: fold 1/0 (signed)
455 InstructionFoldingCase<uint32_t>(
456 Header() + "%main = OpFunction %void None %void_func\n" +
457 "%main_lab = OpLabel\n" +
458 "%2 = OpSDiv %int %int_1 %int_0\n" +
459 "OpReturn\n" +
460 "OpFunctionEnd",
461 2, 0),
462 // Test case 18: fold 1/0 (unsigned)
463 InstructionFoldingCase<uint32_t>(
464 Header() + "%main = OpFunction %void None %void_func\n" +
465 "%main_lab = OpLabel\n" +
466 "%2 = OpUDiv %uint %uint_1 %uint_0\n" +
467 "OpReturn\n" +
468 "OpFunctionEnd",
469 2, 0),
470 // Test case 19: fold OpSRem 1 0 (signed)
471 InstructionFoldingCase<uint32_t>(
472 Header() + "%main = OpFunction %void None %void_func\n" +
473 "%main_lab = OpLabel\n" +
474 "%2 = OpSRem %int %int_1 %int_0\n" +
475 "OpReturn\n" +
476 "OpFunctionEnd",
477 2, 0),
478 // Test case 20: fold 1%0 (signed)
479 InstructionFoldingCase<uint32_t>(
480 Header() + "%main = OpFunction %void None %void_func\n" +
481 "%main_lab = OpLabel\n" +
482 "%2 = OpSMod %int %int_1 %int_0\n" +
483 "OpReturn\n" +
484 "OpFunctionEnd",
485 2, 0),
486 // Test case 21: fold 1%0 (unsigned)
487 InstructionFoldingCase<uint32_t>(
488 Header() + "%main = OpFunction %void None %void_func\n" +
489 "%main_lab = OpLabel\n" +
490 "%2 = OpUMod %uint %uint_1 %uint_0\n" +
491 "OpReturn\n" +
492 "OpFunctionEnd",
493 2, 0),
494 // Test case 22: fold unsigned n >> 42 (undefined, so set to zero).
495 InstructionFoldingCase<uint32_t>(
496 Header() + "%main = OpFunction %void None %void_func\n" +
497 "%main_lab = OpLabel\n" +
498 "%n = OpVariable %_ptr_uint Function\n" +
499 "%load = OpLoad %uint %n\n" +
500 "%2 = OpShiftRightLogical %uint %load %uint_42\n" +
501 "OpReturn\n" +
502 "OpFunctionEnd",
503 2, 0),
504 // Test case 23: fold signed n >> 42 (undefined, so set to zero).
505 InstructionFoldingCase<uint32_t>(
506 Header() + "%main = OpFunction %void None %void_func\n" +
507 "%main_lab = OpLabel\n" +
508 "%n = OpVariable %_ptr_int Function\n" +
509 "%load = OpLoad %int %n\n" +
510 "%2 = OpShiftRightLogical %int %load %uint_42\n" +
511 "OpReturn\n" +
512 "OpFunctionEnd",
513 2, 0),
514 // Test case 24: fold n << 42 (undefined, so set to zero).
515 InstructionFoldingCase<uint32_t>(
516 Header() + "%main = OpFunction %void None %void_func\n" +
517 "%main_lab = OpLabel\n" +
518 "%n = OpVariable %_ptr_int Function\n" +
519 "%load = OpLoad %int %n\n" +
520 "%2 = OpShiftLeftLogical %int %load %uint_42\n" +
521 "OpReturn\n" +
522 "OpFunctionEnd",
523 2, 0),
524 // Test case 25: fold -24 >> 32 (defined as -1)
525 InstructionFoldingCase<uint32_t>(
526 Header() + "%main = OpFunction %void None %void_func\n" +
527 "%main_lab = OpLabel\n" +
528 "%2 = OpShiftRightArithmetic %int %int_n24 %uint_32\n" +
529 "OpReturn\n" +
530 "OpFunctionEnd",
531 2, -1),
532 // Test case 26: fold 2 >> 32 (signed)
533 InstructionFoldingCase<uint32_t>(
534 Header() + "%main = OpFunction %void None %void_func\n" +
535 "%main_lab = OpLabel\n" +
536 "%2 = OpShiftRightArithmetic %int %int_2 %uint_32\n" +
537 "OpReturn\n" +
538 "OpFunctionEnd",
539 2, 0),
540 // Test case 27: fold 2 >> 32 (unsigned)
541 InstructionFoldingCase<uint32_t>(
542 Header() + "%main = OpFunction %void None %void_func\n" +
543 "%main_lab = OpLabel\n" +
544 "%2 = OpShiftRightLogical %int %int_2 %uint_32\n" +
545 "OpReturn\n" +
546 "OpFunctionEnd",
547 2, 0),
548 // Test case 28: fold 2 << 32
549 InstructionFoldingCase<uint32_t>(
550 Header() + "%main = OpFunction %void None %void_func\n" +
551 "%main_lab = OpLabel\n" +
552 "%2 = OpShiftLeftLogical %int %int_2 %uint_32\n" +
553 "OpReturn\n" +
554 "OpFunctionEnd",
555 2, 0),
556 // Test case 29: fold -INT_MIN
557 InstructionFoldingCase<uint32_t>(
558 Header() + "%main = OpFunction %void None %void_func\n" +
559 "%main_lab = OpLabel\n" +
560 "%2 = OpSNegate %int %int_min\n" +
561 "OpReturn\n" +
562 "OpFunctionEnd",
563 2, std::numeric_limits<int32_t>::min()),
564 // Test case 30: fold UMin 3 4
565 InstructionFoldingCase<uint32_t>(
566 Header() + "%main = OpFunction %void None %void_func\n" +
567 "%main_lab = OpLabel\n" +
568 "%2 = OpExtInst %uint %1 UMin %uint_3 %uint_4\n" +
569 "OpReturn\n" +
570 "OpFunctionEnd",
571 2, 3),
572 // Test case 31: fold UMin 4 2
573 InstructionFoldingCase<uint32_t>(
574 Header() + "%main = OpFunction %void None %void_func\n" +
575 "%main_lab = OpLabel\n" +
576 "%2 = OpExtInst %uint %1 UMin %uint_4 %uint_2\n" +
577 "OpReturn\n" +
578 "OpFunctionEnd",
579 2, 2),
580 // Test case 32: fold SMin 3 4
581 InstructionFoldingCase<uint32_t>(
582 Header() + "%main = OpFunction %void None %void_func\n" +
583 "%main_lab = OpLabel\n" +
584 "%2 = OpExtInst %int %1 UMin %int_3 %int_4\n" +
585 "OpReturn\n" +
586 "OpFunctionEnd",
587 2, 3),
588 // Test case 33: fold SMin 4 2
589 InstructionFoldingCase<uint32_t>(
590 Header() + "%main = OpFunction %void None %void_func\n" +
591 "%main_lab = OpLabel\n" +
592 "%2 = OpExtInst %int %1 SMin %int_4 %int_2\n" +
593 "OpReturn\n" +
594 "OpFunctionEnd",
595 2, 2),
596 // Test case 34: fold UMax 3 4
597 InstructionFoldingCase<uint32_t>(
598 Header() + "%main = OpFunction %void None %void_func\n" +
599 "%main_lab = OpLabel\n" +
600 "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_4\n" +
601 "OpReturn\n" +
602 "OpFunctionEnd",
603 2, 4),
604 // Test case 35: fold UMax 3 2
605 InstructionFoldingCase<uint32_t>(
606 Header() + "%main = OpFunction %void None %void_func\n" +
607 "%main_lab = OpLabel\n" +
608 "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_2\n" +
609 "OpReturn\n" +
610 "OpFunctionEnd",
611 2, 3),
612 // Test case 36: fold SMax 3 4
613 InstructionFoldingCase<uint32_t>(
614 Header() + "%main = OpFunction %void None %void_func\n" +
615 "%main_lab = OpLabel\n" +
616 "%2 = OpExtInst %int %1 UMax %int_3 %int_4\n" +
617 "OpReturn\n" +
618 "OpFunctionEnd",
619 2, 4),
620 // Test case 37: fold SMax 3 2
621 InstructionFoldingCase<uint32_t>(
622 Header() + "%main = OpFunction %void None %void_func\n" +
623 "%main_lab = OpLabel\n" +
624 "%2 = OpExtInst %int %1 SMax %int_3 %int_2\n" +
625 "OpReturn\n" +
626 "OpFunctionEnd",
627 2, 3),
628 // Test case 38: fold UClamp 2 3 4
629 InstructionFoldingCase<uint32_t>(
630 Header() + "%main = OpFunction %void None %void_func\n" +
631 "%main_lab = OpLabel\n" +
632 "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_3 %uint_4\n" +
633 "OpReturn\n" +
634 "OpFunctionEnd",
635 2, 3),
636 // Test case 39: fold UClamp 2 0 4
637 InstructionFoldingCase<uint32_t>(
638 Header() + "%main = OpFunction %void None %void_func\n" +
639 "%main_lab = OpLabel\n" +
640 "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_4\n" +
641 "OpReturn\n" +
642 "OpFunctionEnd",
643 2, 2),
644 // Test case 40: fold UClamp 2 0 1
645 InstructionFoldingCase<uint32_t>(
646 Header() + "%main = OpFunction %void None %void_func\n" +
647 "%main_lab = OpLabel\n" +
648 "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_1\n" +
649 "OpReturn\n" +
650 "OpFunctionEnd",
651 2, 1),
652 // Test case 41: fold SClamp 2 3 4
653 InstructionFoldingCase<uint32_t>(
654 Header() + "%main = OpFunction %void None %void_func\n" +
655 "%main_lab = OpLabel\n" +
656 "%2 = OpExtInst %int %1 SClamp %int_2 %int_3 %int_4\n" +
657 "OpReturn\n" +
658 "OpFunctionEnd",
659 2, 3),
660 // Test case 42: fold SClamp 2 0 4
661 InstructionFoldingCase<uint32_t>(
662 Header() + "%main = OpFunction %void None %void_func\n" +
663 "%main_lab = OpLabel\n" +
664 "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_4\n" +
665 "OpReturn\n" +
666 "OpFunctionEnd",
667 2, 2),
668 // Test case 43: fold SClamp 2 0 1
669 InstructionFoldingCase<uint32_t>(
670 Header() + "%main = OpFunction %void None %void_func\n" +
671 "%main_lab = OpLabel\n" +
672 "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_1\n" +
673 "OpReturn\n" +
674 "OpFunctionEnd",
675 2, 1),
676 // Test case 44: SClamp 1 2 x
677 InstructionFoldingCase<uint32_t>(
678 Header() + "%main = OpFunction %void None %void_func\n" +
679 "%main_lab = OpLabel\n" +
680 "%undef = OpUndef %int\n" +
681 "%2 = OpExtInst %int %1 SClamp %int_1 %int_2 %undef\n" +
682 "OpReturn\n" +
683 "OpFunctionEnd",
684 2, 2),
685 // Test case 45: SClamp 2 x 1
686 InstructionFoldingCase<uint32_t>(
687 Header() + "%main = OpFunction %void None %void_func\n" +
688 "%main_lab = OpLabel\n" +
689 "%undef = OpUndef %int\n" +
690 "%2 = OpExtInst %int %1 SClamp %int_2 %undef %int_1\n" +
691 "OpReturn\n" +
692 "OpFunctionEnd",
693 2, 1),
694 // Test case 44: UClamp 1 2 x
695 InstructionFoldingCase<uint32_t>(
696 Header() + "%main = OpFunction %void None %void_func\n" +
697 "%main_lab = OpLabel\n" +
698 "%undef = OpUndef %uint\n" +
699 "%2 = OpExtInst %uint %1 UClamp %uint_1 %uint_2 %undef\n" +
700 "OpReturn\n" +
701 "OpFunctionEnd",
702 2, 2),
703 // Test case 45: UClamp 2 x 1
704 InstructionFoldingCase<uint32_t>(
705 Header() + "%main = OpFunction %void None %void_func\n" +
706 "%main_lab = OpLabel\n" +
707 "%undef = OpUndef %uint\n" +
708 "%2 = OpExtInst %uint %1 UClamp %uint_2 %undef %uint_1\n" +
709 "OpReturn\n" +
710 "OpFunctionEnd",
711 2, 1)
712 ));
713 // clang-format on
714
715 using IntVectorInstructionFoldingTest =
716 ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint32_t>>>;
717
TEST_P(IntVectorInstructionFoldingTest,Case)718 TEST_P(IntVectorInstructionFoldingTest, Case) {
719 const auto& tc = GetParam();
720
721 // Build module.
722 std::unique_ptr<IRContext> context =
723 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
724 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
725 ASSERT_NE(nullptr, context);
726
727 // Fold the instruction to test.
728 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
729 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
730 SpvOp original_opcode = inst->opcode();
731 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
732
733 // Make sure the instruction folded as expected.
734 EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
735 if (succeeded && inst != nullptr) {
736 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
737 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
738 std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
739 EXPECT_THAT(opcodes, Contains(inst->opcode()));
740 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
741 const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
742 EXPECT_NE(result, nullptr);
743 if (result != nullptr) {
744 const std::vector<const analysis::Constant*>& componenets =
745 result->AsVectorConstant()->GetComponents();
746 EXPECT_EQ(componenets.size(), tc.expected_result.size());
747 for (size_t i = 0; i < componenets.size(); i++) {
748 EXPECT_EQ(tc.expected_result[i], componenets[i]->GetU32());
749 }
750 }
751 }
752 }
753
754 // clang-format off
755 INSTANTIATE_TEST_SUITE_P(TestCase, IntVectorInstructionFoldingTest,
756 ::testing::Values(
757 // Test case 0: fold 0*n
758 InstructionFoldingCase<std::vector<uint32_t>>(
759 Header() + "%main = OpFunction %void None %void_func\n" +
760 "%main_lab = OpLabel\n" +
761 "%n = OpVariable %_ptr_int Function\n" +
762 "%load = OpLoad %int %n\n" +
763 "%2 = OpVectorShuffle %v2int %v2int_2_2 %v2int_2_3 0 3\n" +
764 "OpReturn\n" +
765 "OpFunctionEnd",
766 2, {2,3}),
767 InstructionFoldingCase<std::vector<uint32_t>>(
768 Header() + "%main = OpFunction %void None %void_func\n" +
769 "%main_lab = OpLabel\n" +
770 "%n = OpVariable %_ptr_int Function\n" +
771 "%load = OpLoad %int %n\n" +
772 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
773 "OpReturn\n" +
774 "OpFunctionEnd",
775 2, {0,3}),
776 InstructionFoldingCase<std::vector<uint32_t>>(
777 Header() + "%main = OpFunction %void None %void_func\n" +
778 "%main_lab = OpLabel\n" +
779 "%n = OpVariable %_ptr_int Function\n" +
780 "%load = OpLoad %int %n\n" +
781 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 4294967295 3\n" +
782 "OpReturn\n" +
783 "OpFunctionEnd",
784 2, {0,0}),
785 InstructionFoldingCase<std::vector<uint32_t>>(
786 Header() + "%main = OpFunction %void None %void_func\n" +
787 "%main_lab = OpLabel\n" +
788 "%n = OpVariable %_ptr_int Function\n" +
789 "%load = OpLoad %int %n\n" +
790 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 4294967295 \n" +
791 "OpReturn\n" +
792 "OpFunctionEnd",
793 2, {0,0})
794 ));
795 // clang-format on
796
797 using FloatVectorInstructionFoldingTest =
798 ::testing::TestWithParam<InstructionFoldingCase<std::vector<float>>>;
799
TEST_P(FloatVectorInstructionFoldingTest,Case)800 TEST_P(FloatVectorInstructionFoldingTest, Case) {
801 const auto& tc = GetParam();
802
803 // Build module.
804 std::unique_ptr<IRContext> context =
805 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
806 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
807 ASSERT_NE(nullptr, context);
808
809 // Fold the instruction to test.
810 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
811 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
812 SpvOp original_opcode = inst->opcode();
813 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
814
815 // Make sure the instruction folded as expected.
816 EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
817 if (succeeded && inst != nullptr) {
818 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
819 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
820 std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
821 EXPECT_THAT(opcodes, Contains(inst->opcode()));
822 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
823 const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
824 EXPECT_NE(result, nullptr);
825 if (result != nullptr) {
826 const std::vector<const analysis::Constant*>& componenets =
827 result->AsVectorConstant()->GetComponents();
828 EXPECT_EQ(componenets.size(), tc.expected_result.size());
829 for (size_t i = 0; i < componenets.size(); i++) {
830 EXPECT_EQ(tc.expected_result[i], componenets[i]->GetFloat());
831 }
832 }
833 }
834 }
835
836 // clang-format off
837 INSTANTIATE_TEST_SUITE_P(TestCase, FloatVectorInstructionFoldingTest,
838 ::testing::Values(
839 // Test case 0: FMix {2.0, 2.0}, {2.0, 3.0} {0.2,0.5}
840 InstructionFoldingCase<std::vector<float>>(
841 Header() + "%main = OpFunction %void None %void_func\n" +
842 "%main_lab = OpLabel\n" +
843 "%2 = OpExtInst %v2float %1 FMix %v2float_2_3 %v2float_0_0 %v2float_0p2_0p5\n" +
844 "OpReturn\n" +
845 "OpFunctionEnd",
846 2, {1.6f,1.5f})
847 ));
848 // clang-format on
849 using BooleanInstructionFoldingTest =
850 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
851
TEST_P(BooleanInstructionFoldingTest,Case)852 TEST_P(BooleanInstructionFoldingTest, Case) {
853 const auto& tc = GetParam();
854
855 // Build module.
856 std::unique_ptr<IRContext> context =
857 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
858 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
859 ASSERT_NE(nullptr, context);
860
861 // Fold the instruction to test.
862 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
863 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
864 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
865
866 // Make sure the instruction folded as expected.
867 EXPECT_TRUE(succeeded);
868 if (inst != nullptr) {
869 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
870 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
871 std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
872 EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
873 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
874 const analysis::BoolConstant* result =
875 const_mrg->GetConstantFromInst(inst)->AsBoolConstant();
876 EXPECT_NE(result, nullptr);
877 if (result != nullptr) {
878 EXPECT_EQ(result->value(), tc.expected_result);
879 }
880 }
881 }
882
883 // clang-format off
884 INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTest,
885 ::testing::Values(
886 // Test case 0: fold true || n
887 InstructionFoldingCase<bool>(
888 Header() + "%main = OpFunction %void None %void_func\n" +
889 "%main_lab = OpLabel\n" +
890 "%n = OpVariable %_ptr_bool Function\n" +
891 "%load = OpLoad %bool %n\n" +
892 "%2 = OpLogicalOr %bool %true %load\n" +
893 "OpReturn\n" +
894 "OpFunctionEnd",
895 2, true),
896 // Test case 1: fold n || true
897 InstructionFoldingCase<bool>(
898 Header() + "%main = OpFunction %void None %void_func\n" +
899 "%main_lab = OpLabel\n" +
900 "%n = OpVariable %_ptr_bool Function\n" +
901 "%load = OpLoad %bool %n\n" +
902 "%2 = OpLogicalOr %bool %load %true\n" +
903 "OpReturn\n" +
904 "OpFunctionEnd",
905 2, true),
906 // Test case 2: fold false && n
907 InstructionFoldingCase<bool>(
908 Header() + "%main = OpFunction %void None %void_func\n" +
909 "%main_lab = OpLabel\n" +
910 "%n = OpVariable %_ptr_bool Function\n" +
911 "%load = OpLoad %bool %n\n" +
912 "%2 = OpLogicalAnd %bool %false %load\n" +
913 "OpReturn\n" +
914 "OpFunctionEnd",
915 2, false),
916 // Test case 3: fold n && false
917 InstructionFoldingCase<bool>(
918 Header() + "%main = OpFunction %void None %void_func\n" +
919 "%main_lab = OpLabel\n" +
920 "%n = OpVariable %_ptr_bool Function\n" +
921 "%load = OpLoad %bool %n\n" +
922 "%2 = OpLogicalAnd %bool %load %false\n" +
923 "OpReturn\n" +
924 "OpFunctionEnd",
925 2, false),
926 // Test case 4: fold n < 0 (unsigned)
927 InstructionFoldingCase<bool>(
928 Header() + "%main = OpFunction %void None %void_func\n" +
929 "%main_lab = OpLabel\n" +
930 "%n = OpVariable %_ptr_uint Function\n" +
931 "%load = OpLoad %uint %n\n" +
932 "%2 = OpULessThan %bool %load %uint_0\n" +
933 "OpReturn\n" +
934 "OpFunctionEnd",
935 2, false),
936 // Test case 5: fold UINT_MAX < n (unsigned)
937 InstructionFoldingCase<bool>(
938 Header() + "%main = OpFunction %void None %void_func\n" +
939 "%main_lab = OpLabel\n" +
940 "%n = OpVariable %_ptr_uint Function\n" +
941 "%load = OpLoad %uint %n\n" +
942 "%2 = OpULessThan %bool %uint_max %load\n" +
943 "OpReturn\n" +
944 "OpFunctionEnd",
945 2, false),
946 // Test case 6: fold INT_MAX < n (signed)
947 InstructionFoldingCase<bool>(
948 Header() + "%main = OpFunction %void None %void_func\n" +
949 "%main_lab = OpLabel\n" +
950 "%n = OpVariable %_ptr_int Function\n" +
951 "%load = OpLoad %int %n\n" +
952 "%2 = OpSLessThan %bool %int_max %load\n" +
953 "OpReturn\n" +
954 "OpFunctionEnd",
955 2, false),
956 // Test case 7: fold n < INT_MIN (signed)
957 InstructionFoldingCase<bool>(
958 Header() + "%main = OpFunction %void None %void_func\n" +
959 "%main_lab = OpLabel\n" +
960 "%n = OpVariable %_ptr_int Function\n" +
961 "%load = OpLoad %int %n\n" +
962 "%2 = OpSLessThan %bool %load %int_min\n" +
963 "OpReturn\n" +
964 "OpFunctionEnd",
965 2, false),
966 // Test case 8: fold 0 > n (unsigned)
967 InstructionFoldingCase<bool>(
968 Header() + "%main = OpFunction %void None %void_func\n" +
969 "%main_lab = OpLabel\n" +
970 "%n = OpVariable %_ptr_uint Function\n" +
971 "%load = OpLoad %uint %n\n" +
972 "%2 = OpUGreaterThan %bool %uint_0 %load\n" +
973 "OpReturn\n" +
974 "OpFunctionEnd",
975 2, false),
976 // Test case 9: fold n > UINT_MAX (unsigned)
977 InstructionFoldingCase<bool>(
978 Header() + "%main = OpFunction %void None %void_func\n" +
979 "%main_lab = OpLabel\n" +
980 "%n = OpVariable %_ptr_uint Function\n" +
981 "%load = OpLoad %uint %n\n" +
982 "%2 = OpUGreaterThan %bool %load %uint_max\n" +
983 "OpReturn\n" +
984 "OpFunctionEnd",
985 2, false),
986 // Test case 10: fold n > INT_MAX (signed)
987 InstructionFoldingCase<bool>(
988 Header() + "%main = OpFunction %void None %void_func\n" +
989 "%main_lab = OpLabel\n" +
990 "%n = OpVariable %_ptr_int Function\n" +
991 "%load = OpLoad %int %n\n" +
992 "%2 = OpSGreaterThan %bool %load %int_max\n" +
993 "OpReturn\n" +
994 "OpFunctionEnd",
995 2, false),
996 // Test case 11: fold INT_MIN > n (signed)
997 InstructionFoldingCase<bool>(
998 Header() + "%main = OpFunction %void None %void_func\n" +
999 "%main_lab = OpLabel\n" +
1000 "%n = OpVariable %_ptr_uint Function\n" +
1001 "%load = OpLoad %uint %n\n" +
1002 "%2 = OpSGreaterThan %bool %int_min %load\n" +
1003 "OpReturn\n" +
1004 "OpFunctionEnd",
1005 2, false),
1006 // Test case 12: fold 0 <= n (unsigned)
1007 InstructionFoldingCase<bool>(
1008 Header() + "%main = OpFunction %void None %void_func\n" +
1009 "%main_lab = OpLabel\n" +
1010 "%n = OpVariable %_ptr_uint Function\n" +
1011 "%load = OpLoad %uint %n\n" +
1012 "%2 = OpULessThanEqual %bool %uint_0 %load\n" +
1013 "OpReturn\n" +
1014 "OpFunctionEnd",
1015 2, true),
1016 // Test case 13: fold n <= UINT_MAX (unsigned)
1017 InstructionFoldingCase<bool>(
1018 Header() + "%main = OpFunction %void None %void_func\n" +
1019 "%main_lab = OpLabel\n" +
1020 "%n = OpVariable %_ptr_uint Function\n" +
1021 "%load = OpLoad %uint %n\n" +
1022 "%2 = OpULessThanEqual %bool %load %uint_max\n" +
1023 "OpReturn\n" +
1024 "OpFunctionEnd",
1025 2, true),
1026 // Test case 14: fold INT_MIN <= n (signed)
1027 InstructionFoldingCase<bool>(
1028 Header() + "%main = OpFunction %void None %void_func\n" +
1029 "%main_lab = OpLabel\n" +
1030 "%n = OpVariable %_ptr_int Function\n" +
1031 "%load = OpLoad %int %n\n" +
1032 "%2 = OpSLessThanEqual %bool %int_min %load\n" +
1033 "OpReturn\n" +
1034 "OpFunctionEnd",
1035 2, true),
1036 // Test case 15: fold n <= INT_MAX (signed)
1037 InstructionFoldingCase<bool>(
1038 Header() + "%main = OpFunction %void None %void_func\n" +
1039 "%main_lab = OpLabel\n" +
1040 "%n = OpVariable %_ptr_int Function\n" +
1041 "%load = OpLoad %int %n\n" +
1042 "%2 = OpSLessThanEqual %bool %load %int_max\n" +
1043 "OpReturn\n" +
1044 "OpFunctionEnd",
1045 2, true),
1046 // Test case 16: fold n >= 0 (unsigned)
1047 InstructionFoldingCase<bool>(
1048 Header() + "%main = OpFunction %void None %void_func\n" +
1049 "%main_lab = OpLabel\n" +
1050 "%n = OpVariable %_ptr_uint Function\n" +
1051 "%load = OpLoad %uint %n\n" +
1052 "%2 = OpUGreaterThanEqual %bool %load %uint_0\n" +
1053 "OpReturn\n" +
1054 "OpFunctionEnd",
1055 2, true),
1056 // Test case 17: fold UINT_MAX >= n (unsigned)
1057 InstructionFoldingCase<bool>(
1058 Header() + "%main = OpFunction %void None %void_func\n" +
1059 "%main_lab = OpLabel\n" +
1060 "%n = OpVariable %_ptr_uint Function\n" +
1061 "%load = OpLoad %uint %n\n" +
1062 "%2 = OpUGreaterThanEqual %bool %uint_max %load\n" +
1063 "OpReturn\n" +
1064 "OpFunctionEnd",
1065 2, true),
1066 // Test case 18: fold n >= INT_MIN (signed)
1067 InstructionFoldingCase<bool>(
1068 Header() + "%main = OpFunction %void None %void_func\n" +
1069 "%main_lab = OpLabel\n" +
1070 "%n = OpVariable %_ptr_int Function\n" +
1071 "%load = OpLoad %int %n\n" +
1072 "%2 = OpSGreaterThanEqual %bool %load %int_min\n" +
1073 "OpReturn\n" +
1074 "OpFunctionEnd",
1075 2, true),
1076 // Test case 19: fold INT_MAX >= n (signed)
1077 InstructionFoldingCase<bool>(
1078 Header() + "%main = OpFunction %void None %void_func\n" +
1079 "%main_lab = OpLabel\n" +
1080 "%n = OpVariable %_ptr_int Function\n" +
1081 "%load = OpLoad %int %n\n" +
1082 "%2 = OpSGreaterThanEqual %bool %int_max %load\n" +
1083 "OpReturn\n" +
1084 "OpFunctionEnd",
1085 2, true)
1086 ));
1087
1088 INSTANTIATE_TEST_SUITE_P(FClampAndCmpLHS, BooleanInstructionFoldingTest,
1089 ::testing::Values(
1090 // Test case 0: fold 0.0 > clamp(n, 0.0, 1.0)
1091 InstructionFoldingCase<bool>(
1092 Header() + "%main = OpFunction %void None %void_func\n" +
1093 "%main_lab = OpLabel\n" +
1094 "%n = OpVariable %_ptr_float Function\n" +
1095 "%ld = OpLoad %float %n\n" +
1096 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1097 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
1098 "OpReturn\n" +
1099 "OpFunctionEnd",
1100 2, false),
1101 // Test case 1: fold 0.0 > clamp(n, -1.0, -1.0)
1102 InstructionFoldingCase<bool>(
1103 Header() + "%main = OpFunction %void None %void_func\n" +
1104 "%main_lab = OpLabel\n" +
1105 "%n = OpVariable %_ptr_float Function\n" +
1106 "%ld = OpLoad %float %n\n" +
1107 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
1108 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
1109 "OpReturn\n" +
1110 "OpFunctionEnd",
1111 2, true),
1112 // Test case 2: fold 0.0 >= clamp(n, 1, 2)
1113 InstructionFoldingCase<bool>(
1114 Header() + "%main = OpFunction %void None %void_func\n" +
1115 "%main_lab = OpLabel\n" +
1116 "%n = OpVariable %_ptr_float Function\n" +
1117 "%ld = OpLoad %float %n\n" +
1118 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1119 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
1120 "OpReturn\n" +
1121 "OpFunctionEnd",
1122 2, false),
1123 // Test case 3: fold 0.0 >= clamp(n, -1.0, 0.0)
1124 InstructionFoldingCase<bool>(
1125 Header() + "%main = OpFunction %void None %void_func\n" +
1126 "%main_lab = OpLabel\n" +
1127 "%n = OpVariable %_ptr_float Function\n" +
1128 "%ld = OpLoad %float %n\n" +
1129 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1130 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
1131 "OpReturn\n" +
1132 "OpFunctionEnd",
1133 2, true),
1134 // Test case 4: fold 0.0 <= clamp(n, 0.0, 1.0)
1135 InstructionFoldingCase<bool>(
1136 Header() + "%main = OpFunction %void None %void_func\n" +
1137 "%main_lab = OpLabel\n" +
1138 "%n = OpVariable %_ptr_float Function\n" +
1139 "%ld = OpLoad %float %n\n" +
1140 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1141 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
1142 "OpReturn\n" +
1143 "OpFunctionEnd",
1144 2, true),
1145 // Test case 5: fold 0.0 <= clamp(n, -1.0, -1.0)
1146 InstructionFoldingCase<bool>(
1147 Header() + "%main = OpFunction %void None %void_func\n" +
1148 "%main_lab = OpLabel\n" +
1149 "%n = OpVariable %_ptr_float Function\n" +
1150 "%ld = OpLoad %float %n\n" +
1151 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
1152 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
1153 "OpReturn\n" +
1154 "OpFunctionEnd",
1155 2, false),
1156 // Test case 6: fold 0.0 < clamp(n, 1, 2)
1157 InstructionFoldingCase<bool>(
1158 Header() + "%main = OpFunction %void None %void_func\n" +
1159 "%main_lab = OpLabel\n" +
1160 "%n = OpVariable %_ptr_float Function\n" +
1161 "%ld = OpLoad %float %n\n" +
1162 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1163 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
1164 "OpReturn\n" +
1165 "OpFunctionEnd",
1166 2, true),
1167 // Test case 7: fold 0.0 < clamp(n, -1.0, 0.0)
1168 InstructionFoldingCase<bool>(
1169 Header() + "%main = OpFunction %void None %void_func\n" +
1170 "%main_lab = OpLabel\n" +
1171 "%n = OpVariable %_ptr_float Function\n" +
1172 "%ld = OpLoad %float %n\n" +
1173 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1174 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
1175 "OpReturn\n" +
1176 "OpFunctionEnd",
1177 2, false),
1178 // Test case 8: fold 0.0 > clamp(n, 0.0, 1.0)
1179 InstructionFoldingCase<bool>(
1180 Header() + "%main = OpFunction %void None %void_func\n" +
1181 "%main_lab = OpLabel\n" +
1182 "%n = OpVariable %_ptr_float Function\n" +
1183 "%ld = OpLoad %float %n\n" +
1184 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1185 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
1186 "OpReturn\n" +
1187 "OpFunctionEnd",
1188 2, false),
1189 // Test case 9: fold 0.0 > clamp(n, -1.0, -1.0)
1190 InstructionFoldingCase<bool>(
1191 Header() + "%main = OpFunction %void None %void_func\n" +
1192 "%main_lab = OpLabel\n" +
1193 "%n = OpVariable %_ptr_float Function\n" +
1194 "%ld = OpLoad %float %n\n" +
1195 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
1196 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
1197 "OpReturn\n" +
1198 "OpFunctionEnd",
1199 2, true),
1200 // Test case 10: fold 0.0 >= clamp(n, 1, 2)
1201 InstructionFoldingCase<bool>(
1202 Header() + "%main = OpFunction %void None %void_func\n" +
1203 "%main_lab = OpLabel\n" +
1204 "%n = OpVariable %_ptr_float Function\n" +
1205 "%ld = OpLoad %float %n\n" +
1206 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1207 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
1208 "OpReturn\n" +
1209 "OpFunctionEnd",
1210 2, false),
1211 // Test case 11: fold 0.0 >= clamp(n, -1.0, 0.0)
1212 InstructionFoldingCase<bool>(
1213 Header() + "%main = OpFunction %void None %void_func\n" +
1214 "%main_lab = OpLabel\n" +
1215 "%n = OpVariable %_ptr_float Function\n" +
1216 "%ld = OpLoad %float %n\n" +
1217 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1218 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
1219 "OpReturn\n" +
1220 "OpFunctionEnd",
1221 2, true),
1222 // Test case 12: fold 0.0 <= clamp(n, 0.0, 1.0)
1223 InstructionFoldingCase<bool>(
1224 Header() + "%main = OpFunction %void None %void_func\n" +
1225 "%main_lab = OpLabel\n" +
1226 "%n = OpVariable %_ptr_float Function\n" +
1227 "%ld = OpLoad %float %n\n" +
1228 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1229 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
1230 "OpReturn\n" +
1231 "OpFunctionEnd",
1232 2, true),
1233 // Test case 13: fold 0.0 <= clamp(n, -1.0, -1.0)
1234 InstructionFoldingCase<bool>(
1235 Header() + "%main = OpFunction %void None %void_func\n" +
1236 "%main_lab = OpLabel\n" +
1237 "%n = OpVariable %_ptr_float Function\n" +
1238 "%ld = OpLoad %float %n\n" +
1239 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
1240 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
1241 "OpReturn\n" +
1242 "OpFunctionEnd",
1243 2, false),
1244 // Test case 14: fold 0.0 < clamp(n, 1, 2)
1245 InstructionFoldingCase<bool>(
1246 Header() + "%main = OpFunction %void None %void_func\n" +
1247 "%main_lab = OpLabel\n" +
1248 "%n = OpVariable %_ptr_float Function\n" +
1249 "%ld = OpLoad %float %n\n" +
1250 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1251 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
1252 "OpReturn\n" +
1253 "OpFunctionEnd",
1254 2, true),
1255 // Test case 15: fold 0.0 < clamp(n, -1.0, 0.0)
1256 InstructionFoldingCase<bool>(
1257 Header() + "%main = OpFunction %void None %void_func\n" +
1258 "%main_lab = OpLabel\n" +
1259 "%n = OpVariable %_ptr_float Function\n" +
1260 "%ld = OpLoad %float %n\n" +
1261 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1262 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
1263 "OpReturn\n" +
1264 "OpFunctionEnd",
1265 2, false)
1266 ));
1267
1268 INSTANTIATE_TEST_SUITE_P(FClampAndCmpRHS, BooleanInstructionFoldingTest,
1269 ::testing::Values(
1270 // Test case 0: fold clamp(n, 0.0, 1.0) > 1.0
1271 InstructionFoldingCase<bool>(
1272 Header() + "%main = OpFunction %void None %void_func\n" +
1273 "%main_lab = OpLabel\n" +
1274 "%n = OpVariable %_ptr_float Function\n" +
1275 "%ld = OpLoad %float %n\n" +
1276 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1277 "%2 = OpFOrdGreaterThan %bool %clamp %float_1\n" +
1278 "OpReturn\n" +
1279 "OpFunctionEnd",
1280 2, false),
1281 // Test case 1: fold clamp(n, 1.0, 1.0) > 0.0
1282 InstructionFoldingCase<bool>(
1283 Header() + "%main = OpFunction %void None %void_func\n" +
1284 "%main_lab = OpLabel\n" +
1285 "%n = OpVariable %_ptr_float Function\n" +
1286 "%ld = OpLoad %float %n\n" +
1287 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
1288 "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
1289 "OpReturn\n" +
1290 "OpFunctionEnd",
1291 2, true),
1292 // Test case 2: fold clamp(n, 1, 2) >= 0.0
1293 InstructionFoldingCase<bool>(
1294 Header() + "%main = OpFunction %void None %void_func\n" +
1295 "%main_lab = OpLabel\n" +
1296 "%n = OpVariable %_ptr_float Function\n" +
1297 "%ld = OpLoad %float %n\n" +
1298 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1299 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
1300 "OpReturn\n" +
1301 "OpFunctionEnd",
1302 2, true),
1303 // Test case 3: fold clamp(n, 1.0, 2.0) >= 3.0
1304 InstructionFoldingCase<bool>(
1305 Header() + "%main = OpFunction %void None %void_func\n" +
1306 "%main_lab = OpLabel\n" +
1307 "%n = OpVariable %_ptr_float Function\n" +
1308 "%ld = OpLoad %float %n\n" +
1309 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1310 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_3\n" +
1311 "OpReturn\n" +
1312 "OpFunctionEnd",
1313 2, false),
1314 // Test case 4: fold clamp(n, 0.0, 1.0) <= 1.0
1315 InstructionFoldingCase<bool>(
1316 Header() + "%main = OpFunction %void None %void_func\n" +
1317 "%main_lab = OpLabel\n" +
1318 "%n = OpVariable %_ptr_float Function\n" +
1319 "%ld = OpLoad %float %n\n" +
1320 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1321 "%2 = OpFOrdLessThanEqual %bool %clamp %float_1\n" +
1322 "OpReturn\n" +
1323 "OpFunctionEnd",
1324 2, true),
1325 // Test case 5: fold clamp(n, 1.0, 2.0) <= 0.0
1326 InstructionFoldingCase<bool>(
1327 Header() + "%main = OpFunction %void None %void_func\n" +
1328 "%main_lab = OpLabel\n" +
1329 "%n = OpVariable %_ptr_float Function\n" +
1330 "%ld = OpLoad %float %n\n" +
1331 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1332 "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
1333 "OpReturn\n" +
1334 "OpFunctionEnd",
1335 2, false),
1336 // Test case 6: fold clamp(n, 1, 2) < 3
1337 InstructionFoldingCase<bool>(
1338 Header() + "%main = OpFunction %void None %void_func\n" +
1339 "%main_lab = OpLabel\n" +
1340 "%n = OpVariable %_ptr_float Function\n" +
1341 "%ld = OpLoad %float %n\n" +
1342 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1343 "%2 = OpFOrdLessThan %bool %clamp %float_3\n" +
1344 "OpReturn\n" +
1345 "OpFunctionEnd",
1346 2, true),
1347 // Test case 7: fold clamp(n, -1.0, 0.0) < -1.0
1348 InstructionFoldingCase<bool>(
1349 Header() + "%main = OpFunction %void None %void_func\n" +
1350 "%main_lab = OpLabel\n" +
1351 "%n = OpVariable %_ptr_float Function\n" +
1352 "%ld = OpLoad %float %n\n" +
1353 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1354 "%2 = OpFOrdLessThan %bool %clamp %float_n1\n" +
1355 "OpReturn\n" +
1356 "OpFunctionEnd",
1357 2, false),
1358 // Test case 8: fold clamp(n, 0.0, 1.0) > 1.0
1359 InstructionFoldingCase<bool>(
1360 Header() + "%main = OpFunction %void None %void_func\n" +
1361 "%main_lab = OpLabel\n" +
1362 "%n = OpVariable %_ptr_float Function\n" +
1363 "%ld = OpLoad %float %n\n" +
1364 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1365 "%2 = OpFUnordGreaterThan %bool %clamp %float_1\n" +
1366 "OpReturn\n" +
1367 "OpFunctionEnd",
1368 2, false),
1369 // Test case 9: fold clamp(n, 1.0, 2.0) > 0.0
1370 InstructionFoldingCase<bool>(
1371 Header() + "%main = OpFunction %void None %void_func\n" +
1372 "%main_lab = OpLabel\n" +
1373 "%n = OpVariable %_ptr_float Function\n" +
1374 "%ld = OpLoad %float %n\n" +
1375 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1376 "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
1377 "OpReturn\n" +
1378 "OpFunctionEnd",
1379 2, true),
1380 // Test case 10: fold clamp(n, 1, 2) >= 3.0
1381 InstructionFoldingCase<bool>(
1382 Header() + "%main = OpFunction %void None %void_func\n" +
1383 "%main_lab = OpLabel\n" +
1384 "%n = OpVariable %_ptr_float Function\n" +
1385 "%ld = OpLoad %float %n\n" +
1386 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1387 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_3\n" +
1388 "OpReturn\n" +
1389 "OpFunctionEnd",
1390 2, false),
1391 // Test case 11: fold clamp(n, -1.0, 0.0) >= -1.0
1392 InstructionFoldingCase<bool>(
1393 Header() + "%main = OpFunction %void None %void_func\n" +
1394 "%main_lab = OpLabel\n" +
1395 "%n = OpVariable %_ptr_float Function\n" +
1396 "%ld = OpLoad %float %n\n" +
1397 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1398 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_n1\n" +
1399 "OpReturn\n" +
1400 "OpFunctionEnd",
1401 2, true),
1402 // Test case 12: fold clamp(n, 0.0, 1.0) <= 1.0
1403 InstructionFoldingCase<bool>(
1404 Header() + "%main = OpFunction %void None %void_func\n" +
1405 "%main_lab = OpLabel\n" +
1406 "%n = OpVariable %_ptr_float Function\n" +
1407 "%ld = OpLoad %float %n\n" +
1408 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1409 "%2 = OpFUnordLessThanEqual %bool %clamp %float_1\n" +
1410 "OpReturn\n" +
1411 "OpFunctionEnd",
1412 2, true),
1413 // Test case 13: fold clamp(n, 1.0, 1.0) <= 0.0
1414 InstructionFoldingCase<bool>(
1415 Header() + "%main = OpFunction %void None %void_func\n" +
1416 "%main_lab = OpLabel\n" +
1417 "%n = OpVariable %_ptr_float Function\n" +
1418 "%ld = OpLoad %float %n\n" +
1419 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
1420 "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
1421 "OpReturn\n" +
1422 "OpFunctionEnd",
1423 2, false),
1424 // Test case 14: fold clamp(n, 1, 2) < 3
1425 InstructionFoldingCase<bool>(
1426 Header() + "%main = OpFunction %void None %void_func\n" +
1427 "%main_lab = OpLabel\n" +
1428 "%n = OpVariable %_ptr_float Function\n" +
1429 "%ld = OpLoad %float %n\n" +
1430 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1431 "%2 = OpFUnordLessThan %bool %clamp %float_3\n" +
1432 "OpReturn\n" +
1433 "OpFunctionEnd",
1434 2, true),
1435 // Test case 15: fold clamp(n, -1.0, 0.0) < -1.0
1436 InstructionFoldingCase<bool>(
1437 Header() + "%main = OpFunction %void None %void_func\n" +
1438 "%main_lab = OpLabel\n" +
1439 "%n = OpVariable %_ptr_float Function\n" +
1440 "%ld = OpLoad %float %n\n" +
1441 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
1442 "%2 = OpFUnordLessThan %bool %clamp %float_n1\n" +
1443 "OpReturn\n" +
1444 "OpFunctionEnd",
1445 2, false),
1446 // Test case 16: fold clamp(n, -1.0, 0.0) < -1.0 (one test for double)
1447 InstructionFoldingCase<bool>(
1448 Header() + "%main = OpFunction %void None %void_func\n" +
1449 "%main_lab = OpLabel\n" +
1450 "%n = OpVariable %_ptr_double Function\n" +
1451 "%ld = OpLoad %double %n\n" +
1452 "%clamp = OpExtInst %double %1 FClamp %ld %double_n1 %double_0\n" +
1453 "%2 = OpFUnordLessThan %bool %clamp %double_n1\n" +
1454 "OpReturn\n" +
1455 "OpFunctionEnd",
1456 2, false)
1457 ));
1458 // clang-format on
1459
1460 using FloatInstructionFoldingTest =
1461 ::testing::TestWithParam<InstructionFoldingCase<float>>;
1462
TEST_P(FloatInstructionFoldingTest,Case)1463 TEST_P(FloatInstructionFoldingTest, Case) {
1464 const auto& tc = GetParam();
1465
1466 // Build module.
1467 std::unique_ptr<IRContext> context =
1468 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
1469 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1470 ASSERT_NE(nullptr, context);
1471
1472 // Fold the instruction to test.
1473 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
1474 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
1475 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
1476
1477 // Make sure the instruction folded as expected.
1478 EXPECT_TRUE(succeeded);
1479 if (inst != nullptr) {
1480 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
1481 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
1482 EXPECT_EQ(inst->opcode(), SpvOpConstant);
1483 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
1484 const analysis::FloatConstant* result =
1485 const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
1486 EXPECT_NE(result, nullptr);
1487 if (result != nullptr) {
1488 if (!std::isnan(tc.expected_result)) {
1489 EXPECT_EQ(result->GetFloatValue(), tc.expected_result);
1490 } else {
1491 EXPECT_TRUE(std::isnan(result->GetFloatValue()));
1492 }
1493 }
1494 }
1495 }
1496
1497 // Not testing NaNs because there are no expectations concerning NaNs according
1498 // to the "Precision and Operation of SPIR-V Instructions" section of the Vulkan
1499 // specification.
1500
1501 // clang-format off
1502 INSTANTIATE_TEST_SUITE_P(FloatConstantFoldingTest, FloatInstructionFoldingTest,
1503 ::testing::Values(
1504 // Test case 0: Fold 2.0 - 1.0
1505 InstructionFoldingCase<float>(
1506 Header() + "%main = OpFunction %void None %void_func\n" +
1507 "%main_lab = OpLabel\n" +
1508 "%2 = OpFSub %float %float_2 %float_1\n" +
1509 "OpReturn\n" +
1510 "OpFunctionEnd",
1511 2, 1.0),
1512 // Test case 1: Fold 2.0 + 1.0
1513 InstructionFoldingCase<float>(
1514 Header() + "%main = OpFunction %void None %void_func\n" +
1515 "%main_lab = OpLabel\n" +
1516 "%2 = OpFAdd %float %float_2 %float_1\n" +
1517 "OpReturn\n" +
1518 "OpFunctionEnd",
1519 2, 3.0),
1520 // Test case 2: Fold 3.0 * 2.0
1521 InstructionFoldingCase<float>(
1522 Header() + "%main = OpFunction %void None %void_func\n" +
1523 "%main_lab = OpLabel\n" +
1524 "%2 = OpFMul %float %float_3 %float_2\n" +
1525 "OpReturn\n" +
1526 "OpFunctionEnd",
1527 2, 6.0),
1528 // Test case 3: Fold 1.0 / 2.0
1529 InstructionFoldingCase<float>(
1530 Header() + "%main = OpFunction %void None %void_func\n" +
1531 "%main_lab = OpLabel\n" +
1532 "%2 = OpFDiv %float %float_1 %float_2\n" +
1533 "OpReturn\n" +
1534 "OpFunctionEnd",
1535 2, 0.5),
1536 // Test case 4: Fold 1.0 / 0.0
1537 InstructionFoldingCase<float>(
1538 Header() + "%main = OpFunction %void None %void_func\n" +
1539 "%main_lab = OpLabel\n" +
1540 "%2 = OpFDiv %float %float_1 %float_0\n" +
1541 "OpReturn\n" +
1542 "OpFunctionEnd",
1543 2, std::numeric_limits<float>::infinity()),
1544 // Test case 5: Fold -1.0 / 0.0
1545 InstructionFoldingCase<float>(
1546 Header() + "%main = OpFunction %void None %void_func\n" +
1547 "%main_lab = OpLabel\n" +
1548 "%2 = OpFDiv %float %float_n1 %float_0\n" +
1549 "OpReturn\n" +
1550 "OpFunctionEnd",
1551 2, -std::numeric_limits<float>::infinity()),
1552 // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
1553 InstructionFoldingCase<float>(
1554 Header() + "%main = OpFunction %void None %void_func\n" +
1555 "%main_lab = OpLabel\n" +
1556 "%2 = OpDot %float %v2float_2_3 %v2float_2_0p5\n" +
1557 "OpReturn\n" +
1558 "OpFunctionEnd",
1559 2, 5.5f),
1560 // Test case 7: Fold (0.0, 0.0) dot v
1561 InstructionFoldingCase<float>(
1562 Header() + "%main = OpFunction %void None %void_func\n" +
1563 "%main_lab = OpLabel\n" +
1564 "%v = OpVariable %_ptr_v2float Function\n" +
1565 "%2 = OpLoad %v2float %v\n" +
1566 "%3 = OpDot %float %v2float_0_0 %2\n" +
1567 "OpReturn\n" +
1568 "OpFunctionEnd",
1569 3, 0.0f),
1570 // Test case 8: Fold v dot (0.0, 0.0)
1571 InstructionFoldingCase<float>(
1572 Header() + "%main = OpFunction %void None %void_func\n" +
1573 "%main_lab = OpLabel\n" +
1574 "%v = OpVariable %_ptr_v2float Function\n" +
1575 "%2 = OpLoad %v2float %v\n" +
1576 "%3 = OpDot %float %2 %v2float_0_0\n" +
1577 "OpReturn\n" +
1578 "OpFunctionEnd",
1579 3, 0.0f),
1580 // Test case 9: Fold Null dot v
1581 InstructionFoldingCase<float>(
1582 Header() + "%main = OpFunction %void None %void_func\n" +
1583 "%main_lab = OpLabel\n" +
1584 "%v = OpVariable %_ptr_v2float Function\n" +
1585 "%2 = OpLoad %v2float %v\n" +
1586 "%3 = OpDot %float %v2float_null %2\n" +
1587 "OpReturn\n" +
1588 "OpFunctionEnd",
1589 3, 0.0f),
1590 // Test case 10: Fold v dot Null
1591 InstructionFoldingCase<float>(
1592 Header() + "%main = OpFunction %void None %void_func\n" +
1593 "%main_lab = OpLabel\n" +
1594 "%v = OpVariable %_ptr_v2float Function\n" +
1595 "%2 = OpLoad %v2float %v\n" +
1596 "%3 = OpDot %float %2 %v2float_null\n" +
1597 "OpReturn\n" +
1598 "OpFunctionEnd",
1599 3, 0.0f),
1600 // Test case 11: Fold -2.0
1601 InstructionFoldingCase<float>(
1602 Header() + "%main = OpFunction %void None %void_func\n" +
1603 "%main_lab = OpLabel\n" +
1604 "%2 = OpFNegate %float %float_2\n" +
1605 "OpReturn\n" +
1606 "OpFunctionEnd",
1607 2, -2),
1608 // Test case 12: QuantizeToF16 1.0
1609 InstructionFoldingCase<float>(
1610 Header() + "%main = OpFunction %void None %void_func\n" +
1611 "%main_lab = OpLabel\n" +
1612 "%2 = OpQuantizeToF16 %float %float_1\n" +
1613 "OpReturn\n" +
1614 "OpFunctionEnd",
1615 2, 1.0),
1616 // Test case 13: QuantizeToF16 positive non exact
1617 InstructionFoldingCase<float>(
1618 Header() + "%main = OpFunction %void None %void_func\n" +
1619 "%main_lab = OpLabel\n" +
1620 "%2 = OpQuantizeToF16 %float %float_2049\n" +
1621 "OpReturn\n" +
1622 "OpFunctionEnd",
1623 2, 2048),
1624 // Test case 14: QuantizeToF16 negative non exact
1625 InstructionFoldingCase<float>(
1626 Header() + "%main = OpFunction %void None %void_func\n" +
1627 "%main_lab = OpLabel\n" +
1628 "%2 = OpQuantizeToF16 %float %float_n2049\n" +
1629 "OpReturn\n" +
1630 "OpFunctionEnd",
1631 2, -2048),
1632 // Test case 15: QuantizeToF16 large positive
1633 InstructionFoldingCase<float>(
1634 Header() + "%main = OpFunction %void None %void_func\n" +
1635 "%main_lab = OpLabel\n" +
1636 "%2 = OpQuantizeToF16 %float %float_1e16\n" +
1637 "OpReturn\n" +
1638 "OpFunctionEnd",
1639 2, std::numeric_limits<float>::infinity()),
1640 // Test case 16: QuantizeToF16 large negative
1641 InstructionFoldingCase<float>(
1642 Header() + "%main = OpFunction %void None %void_func\n" +
1643 "%main_lab = OpLabel\n" +
1644 "%2 = OpQuantizeToF16 %float %float_n1e16\n" +
1645 "OpReturn\n" +
1646 "OpFunctionEnd",
1647 2, -std::numeric_limits<float>::infinity()),
1648 // Test case 17: QuantizeToF16 small positive
1649 InstructionFoldingCase<float>(
1650 Header() + "%main = OpFunction %void None %void_func\n" +
1651 "%main_lab = OpLabel\n" +
1652 "%2 = OpQuantizeToF16 %float %float_1en16\n" +
1653 "OpReturn\n" +
1654 "OpFunctionEnd",
1655 2, 0.0),
1656 // Test case 18: QuantizeToF16 small negative
1657 InstructionFoldingCase<float>(
1658 Header() + "%main = OpFunction %void None %void_func\n" +
1659 "%main_lab = OpLabel\n" +
1660 "%2 = OpQuantizeToF16 %float %float_n1en16\n" +
1661 "OpReturn\n" +
1662 "OpFunctionEnd",
1663 2, 0.0),
1664 // Test case 19: QuantizeToF16 nan
1665 InstructionFoldingCase<float>(
1666 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
1667 "%main_lab = OpLabel\n" +
1668 "%2 = OpQuantizeToF16 %float %float_nan\n" +
1669 "OpReturn\n" +
1670 "OpFunctionEnd",
1671 2, std::numeric_limits<float>::quiet_NaN()),
1672 // Test case 20: FMix 1.0 4.0 0.2
1673 InstructionFoldingCase<float>(
1674 Header() + "%main = OpFunction %void None %void_func\n" +
1675 "%main_lab = OpLabel\n" +
1676 "%2 = OpExtInst %float %1 FMix %float_1 %float_4 %float_0p2\n" +
1677 "OpReturn\n" +
1678 "OpFunctionEnd",
1679 2, 1.6f),
1680 // Test case 21: FMin 1.0 4.0
1681 InstructionFoldingCase<float>(
1682 Header() + "%main = OpFunction %void None %void_func\n" +
1683 "%main_lab = OpLabel\n" +
1684 "%2 = OpExtInst %float %1 FMin %float_1 %float_4\n" +
1685 "OpReturn\n" +
1686 "OpFunctionEnd",
1687 2, 1.0f),
1688 // Test case 22: FMin 4.0 0.2
1689 InstructionFoldingCase<float>(
1690 Header() + "%main = OpFunction %void None %void_func\n" +
1691 "%main_lab = OpLabel\n" +
1692 "%2 = OpExtInst %float %1 FMin %float_4 %float_0p2\n" +
1693 "OpReturn\n" +
1694 "OpFunctionEnd",
1695 2, 0.2f),
1696 // Test case 23: FMax 1.0 4.0
1697 InstructionFoldingCase<float>(
1698 Header() + "%main = OpFunction %void None %void_func\n" +
1699 "%main_lab = OpLabel\n" +
1700 "%2 = OpExtInst %float %1 FMax %float_1 %float_4\n" +
1701 "OpReturn\n" +
1702 "OpFunctionEnd",
1703 2, 4.0f),
1704 // Test case 24: FMax 1.0 0.2
1705 InstructionFoldingCase<float>(
1706 Header() + "%main = OpFunction %void None %void_func\n" +
1707 "%main_lab = OpLabel\n" +
1708 "%2 = OpExtInst %float %1 FMax %float_1 %float_0p2\n" +
1709 "OpReturn\n" +
1710 "OpFunctionEnd",
1711 2, 1.0f),
1712 // Test case 25: FClamp 1.0 0.2 4.0
1713 InstructionFoldingCase<float>(
1714 Header() + "%main = OpFunction %void None %void_func\n" +
1715 "%main_lab = OpLabel\n" +
1716 "%2 = OpExtInst %float %1 FClamp %float_1 %float_0p2 %float_4\n" +
1717 "OpReturn\n" +
1718 "OpFunctionEnd",
1719 2, 1.0f),
1720 // Test case 26: FClamp 0.2 2.0 4.0
1721 InstructionFoldingCase<float>(
1722 Header() + "%main = OpFunction %void None %void_func\n" +
1723 "%main_lab = OpLabel\n" +
1724 "%2 = OpExtInst %float %1 FClamp %float_0p2 %float_2 %float_4\n" +
1725 "OpReturn\n" +
1726 "OpFunctionEnd",
1727 2, 2.0f),
1728 // Test case 27: FClamp 2049.0 2.0 4.0
1729 InstructionFoldingCase<float>(
1730 Header() + "%main = OpFunction %void None %void_func\n" +
1731 "%main_lab = OpLabel\n" +
1732 "%2 = OpExtInst %float %1 FClamp %float_2049 %float_2 %float_4\n" +
1733 "OpReturn\n" +
1734 "OpFunctionEnd",
1735 2, 4.0f),
1736 // Test case 28: FClamp 1.0 2.0 x
1737 InstructionFoldingCase<float>(
1738 Header() + "%main = OpFunction %void None %void_func\n" +
1739 "%main_lab = OpLabel\n" +
1740 "%undef = OpUndef %float\n" +
1741 "%2 = OpExtInst %float %1 FClamp %float_1 %float_2 %undef\n" +
1742 "OpReturn\n" +
1743 "OpFunctionEnd",
1744 2, 2.0),
1745 // Test case 29: FClamp 1.0 x 0.5
1746 InstructionFoldingCase<float>(
1747 Header() + "%main = OpFunction %void None %void_func\n" +
1748 "%main_lab = OpLabel\n" +
1749 "%undef = OpUndef %float\n" +
1750 "%2 = OpExtInst %float %1 FClamp %float_1 %undef %float_0p5\n" +
1751 "OpReturn\n" +
1752 "OpFunctionEnd",
1753 2, 0.5),
1754 // Test case 30: Sin 0.0
1755 InstructionFoldingCase<float>(
1756 Header() + "%main = OpFunction %void None %void_func\n" +
1757 "%main_lab = OpLabel\n" +
1758 "%2 = OpExtInst %float %1 Sin %float_0\n" +
1759 "OpReturn\n" +
1760 "OpFunctionEnd",
1761 2, 0.0),
1762 // Test case 31: Cos 0.0
1763 InstructionFoldingCase<float>(
1764 Header() + "%main = OpFunction %void None %void_func\n" +
1765 "%main_lab = OpLabel\n" +
1766 "%2 = OpExtInst %float %1 Cos %float_0\n" +
1767 "OpReturn\n" +
1768 "OpFunctionEnd",
1769 2, 1.0),
1770 // Test case 32: Tan 0.0
1771 InstructionFoldingCase<float>(
1772 Header() + "%main = OpFunction %void None %void_func\n" +
1773 "%main_lab = OpLabel\n" +
1774 "%2 = OpExtInst %float %1 Tan %float_0\n" +
1775 "OpReturn\n" +
1776 "OpFunctionEnd",
1777 2, 0.0),
1778 // Test case 33: Asin 0.0
1779 InstructionFoldingCase<float>(
1780 Header() + "%main = OpFunction %void None %void_func\n" +
1781 "%main_lab = OpLabel\n" +
1782 "%2 = OpExtInst %float %1 Asin %float_0\n" +
1783 "OpReturn\n" +
1784 "OpFunctionEnd",
1785 2, 0.0),
1786 // Test case 34: Acos 1.0
1787 InstructionFoldingCase<float>(
1788 Header() + "%main = OpFunction %void None %void_func\n" +
1789 "%main_lab = OpLabel\n" +
1790 "%2 = OpExtInst %float %1 Acos %float_1\n" +
1791 "OpReturn\n" +
1792 "OpFunctionEnd",
1793 2, 0.0),
1794 // Test case 35: Atan 0.0
1795 InstructionFoldingCase<float>(
1796 Header() + "%main = OpFunction %void None %void_func\n" +
1797 "%main_lab = OpLabel\n" +
1798 "%2 = OpExtInst %float %1 Atan %float_0\n" +
1799 "OpReturn\n" +
1800 "OpFunctionEnd",
1801 2, 0.0),
1802 // Test case 36: Exp 0.0
1803 InstructionFoldingCase<float>(
1804 Header() + "%main = OpFunction %void None %void_func\n" +
1805 "%main_lab = OpLabel\n" +
1806 "%2 = OpExtInst %float %1 Exp %float_0\n" +
1807 "OpReturn\n" +
1808 "OpFunctionEnd",
1809 2, 1.0),
1810 // Test case 37: Log 1.0
1811 InstructionFoldingCase<float>(
1812 Header() + "%main = OpFunction %void None %void_func\n" +
1813 "%main_lab = OpLabel\n" +
1814 "%2 = OpExtInst %float %1 Log %float_1\n" +
1815 "OpReturn\n" +
1816 "OpFunctionEnd",
1817 2, 0.0),
1818 // Test case 38: Exp2 2.0
1819 InstructionFoldingCase<float>(
1820 Header() + "%main = OpFunction %void None %void_func\n" +
1821 "%main_lab = OpLabel\n" +
1822 "%2 = OpExtInst %float %1 Exp2 %float_2\n" +
1823 "OpReturn\n" +
1824 "OpFunctionEnd",
1825 2, 4.0),
1826 // Test case 39: Log2 4.0
1827 InstructionFoldingCase<float>(
1828 Header() + "%main = OpFunction %void None %void_func\n" +
1829 "%main_lab = OpLabel\n" +
1830 "%2 = OpExtInst %float %1 Log2 %float_4\n" +
1831 "OpReturn\n" +
1832 "OpFunctionEnd",
1833 2, 2.0),
1834 // Test case 40: Sqrt 4.0
1835 InstructionFoldingCase<float>(
1836 Header() + "%main = OpFunction %void None %void_func\n" +
1837 "%main_lab = OpLabel\n" +
1838 "%2 = OpExtInst %float %1 Sqrt %float_4\n" +
1839 "OpReturn\n" +
1840 "OpFunctionEnd",
1841 2, 2.0),
1842 // Test case 41: Atan2 0.0 1.0
1843 InstructionFoldingCase<float>(
1844 Header() + "%main = OpFunction %void None %void_func\n" +
1845 "%main_lab = OpLabel\n" +
1846 "%2 = OpExtInst %float %1 Atan2 %float_0 %float_1\n" +
1847 "OpReturn\n" +
1848 "OpFunctionEnd",
1849 2, 0.0),
1850 // Test case 42: Pow 2.0 3.0
1851 InstructionFoldingCase<float>(
1852 Header() + "%main = OpFunction %void None %void_func\n" +
1853 "%main_lab = OpLabel\n" +
1854 "%2 = OpExtInst %float %1 Pow %float_2 %float_3\n" +
1855 "OpReturn\n" +
1856 "OpFunctionEnd",
1857 2, 8.0)
1858 ));
1859 // clang-format on
1860
1861 using DoubleInstructionFoldingTest =
1862 ::testing::TestWithParam<InstructionFoldingCase<double>>;
1863
TEST_P(DoubleInstructionFoldingTest,Case)1864 TEST_P(DoubleInstructionFoldingTest, Case) {
1865 const auto& tc = GetParam();
1866
1867 // Build module.
1868 std::unique_ptr<IRContext> context =
1869 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
1870 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1871 ASSERT_NE(nullptr, context);
1872
1873 // Fold the instruction to test.
1874 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
1875 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
1876 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
1877
1878 // Make sure the instruction folded as expected.
1879 EXPECT_TRUE(succeeded);
1880 if (inst != nullptr) {
1881 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
1882 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
1883 EXPECT_EQ(inst->opcode(), SpvOpConstant);
1884 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
1885 const analysis::FloatConstant* result =
1886 const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
1887 EXPECT_NE(result, nullptr);
1888 if (result != nullptr) {
1889 EXPECT_EQ(result->GetDoubleValue(), tc.expected_result);
1890 }
1891 }
1892 }
1893
1894 // clang-format off
1895 INSTANTIATE_TEST_SUITE_P(DoubleConstantFoldingTest, DoubleInstructionFoldingTest,
1896 ::testing::Values(
1897 // Test case 0: Fold 2.0 - 1.0
1898 InstructionFoldingCase<double>(
1899 Header() + "%main = OpFunction %void None %void_func\n" +
1900 "%main_lab = OpLabel\n" +
1901 "%2 = OpFSub %double %double_2 %double_1\n" +
1902 "OpReturn\n" +
1903 "OpFunctionEnd",
1904 2, 1.0),
1905 // Test case 1: Fold 2.0 + 1.0
1906 InstructionFoldingCase<double>(
1907 Header() + "%main = OpFunction %void None %void_func\n" +
1908 "%main_lab = OpLabel\n" +
1909 "%2 = OpFAdd %double %double_2 %double_1\n" +
1910 "OpReturn\n" +
1911 "OpFunctionEnd",
1912 2, 3.0),
1913 // Test case 2: Fold 3.0 * 2.0
1914 InstructionFoldingCase<double>(
1915 Header() + "%main = OpFunction %void None %void_func\n" +
1916 "%main_lab = OpLabel\n" +
1917 "%2 = OpFMul %double %double_3 %double_2\n" +
1918 "OpReturn\n" +
1919 "OpFunctionEnd",
1920 2, 6.0),
1921 // Test case 3: Fold 1.0 / 2.0
1922 InstructionFoldingCase<double>(
1923 Header() + "%main = OpFunction %void None %void_func\n" +
1924 "%main_lab = OpLabel\n" +
1925 "%2 = OpFDiv %double %double_1 %double_2\n" +
1926 "OpReturn\n" +
1927 "OpFunctionEnd",
1928 2, 0.5),
1929 // Test case 4: Fold 1.0 / 0.0
1930 InstructionFoldingCase<double>(
1931 Header() + "%main = OpFunction %void None %void_func\n" +
1932 "%main_lab = OpLabel\n" +
1933 "%2 = OpFDiv %double %double_1 %double_0\n" +
1934 "OpReturn\n" +
1935 "OpFunctionEnd",
1936 2, std::numeric_limits<double>::infinity()),
1937 // Test case 5: Fold -1.0 / 0.0
1938 InstructionFoldingCase<double>(
1939 Header() + "%main = OpFunction %void None %void_func\n" +
1940 "%main_lab = OpLabel\n" +
1941 "%2 = OpFDiv %double %double_n1 %double_0\n" +
1942 "OpReturn\n" +
1943 "OpFunctionEnd",
1944 2, -std::numeric_limits<double>::infinity()),
1945 // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
1946 InstructionFoldingCase<double>(
1947 Header() + "%main = OpFunction %void None %void_func\n" +
1948 "%main_lab = OpLabel\n" +
1949 "%2 = OpDot %double %v2double_2_3 %v2double_2_0p5\n" +
1950 "OpReturn\n" +
1951 "OpFunctionEnd",
1952 2, 5.5f),
1953 // Test case 7: Fold (0.0, 0.0) dot v
1954 InstructionFoldingCase<double>(
1955 Header() + "%main = OpFunction %void None %void_func\n" +
1956 "%main_lab = OpLabel\n" +
1957 "%v = OpVariable %_ptr_v2double Function\n" +
1958 "%2 = OpLoad %v2double %v\n" +
1959 "%3 = OpDot %double %v2double_0_0 %2\n" +
1960 "OpReturn\n" +
1961 "OpFunctionEnd",
1962 3, 0.0f),
1963 // Test case 8: Fold v dot (0.0, 0.0)
1964 InstructionFoldingCase<double>(
1965 Header() + "%main = OpFunction %void None %void_func\n" +
1966 "%main_lab = OpLabel\n" +
1967 "%v = OpVariable %_ptr_v2double Function\n" +
1968 "%2 = OpLoad %v2double %v\n" +
1969 "%3 = OpDot %double %2 %v2double_0_0\n" +
1970 "OpReturn\n" +
1971 "OpFunctionEnd",
1972 3, 0.0f),
1973 // Test case 9: Fold Null dot v
1974 InstructionFoldingCase<double>(
1975 Header() + "%main = OpFunction %void None %void_func\n" +
1976 "%main_lab = OpLabel\n" +
1977 "%v = OpVariable %_ptr_v2double Function\n" +
1978 "%2 = OpLoad %v2double %v\n" +
1979 "%3 = OpDot %double %v2double_null %2\n" +
1980 "OpReturn\n" +
1981 "OpFunctionEnd",
1982 3, 0.0f),
1983 // Test case 10: Fold v dot Null
1984 InstructionFoldingCase<double>(
1985 Header() + "%main = OpFunction %void None %void_func\n" +
1986 "%main_lab = OpLabel\n" +
1987 "%v = OpVariable %_ptr_v2double Function\n" +
1988 "%2 = OpLoad %v2double %v\n" +
1989 "%3 = OpDot %double %2 %v2double_null\n" +
1990 "OpReturn\n" +
1991 "OpFunctionEnd",
1992 3, 0.0f),
1993 // Test case 11: Fold -2.0
1994 InstructionFoldingCase<double>(
1995 Header() + "%main = OpFunction %void None %void_func\n" +
1996 "%main_lab = OpLabel\n" +
1997 "%2 = OpFNegate %double %double_2\n" +
1998 "OpReturn\n" +
1999 "OpFunctionEnd",
2000 2, -2),
2001 // Test case 12: FMin 1.0 4.0
2002 InstructionFoldingCase<double>(
2003 Header() + "%main = OpFunction %void None %void_func\n" +
2004 "%main_lab = OpLabel\n" +
2005 "%2 = OpExtInst %double %1 FMin %double_1 %double_4\n" +
2006 "OpReturn\n" +
2007 "OpFunctionEnd",
2008 2, 1.0),
2009 // Test case 13: FMin 4.0 0.2
2010 InstructionFoldingCase<double>(
2011 Header() + "%main = OpFunction %void None %void_func\n" +
2012 "%main_lab = OpLabel\n" +
2013 "%2 = OpExtInst %double %1 FMin %double_4 %double_0p2\n" +
2014 "OpReturn\n" +
2015 "OpFunctionEnd",
2016 2, 0.2),
2017 // Test case 14: FMax 1.0 4.0
2018 InstructionFoldingCase<double>(
2019 Header() + "%main = OpFunction %void None %void_func\n" +
2020 "%main_lab = OpLabel\n" +
2021 "%2 = OpExtInst %double %1 FMax %double_1 %double_4\n" +
2022 "OpReturn\n" +
2023 "OpFunctionEnd",
2024 2, 4.0),
2025 // Test case 15: FMax 1.0 0.2
2026 InstructionFoldingCase<double>(
2027 Header() + "%main = OpFunction %void None %void_func\n" +
2028 "%main_lab = OpLabel\n" +
2029 "%2 = OpExtInst %double %1 FMax %double_1 %double_0p2\n" +
2030 "OpReturn\n" +
2031 "OpFunctionEnd",
2032 2, 1.0),
2033 // Test case 16: FClamp 1.0 0.2 4.0
2034 InstructionFoldingCase<double>(
2035 Header() + "%main = OpFunction %void None %void_func\n" +
2036 "%main_lab = OpLabel\n" +
2037 "%2 = OpExtInst %double %1 FClamp %double_1 %double_0p2 %double_4\n" +
2038 "OpReturn\n" +
2039 "OpFunctionEnd",
2040 2, 1.0),
2041 // Test case 17: FClamp 0.2 2.0 4.0
2042 InstructionFoldingCase<double>(
2043 Header() + "%main = OpFunction %void None %void_func\n" +
2044 "%main_lab = OpLabel\n" +
2045 "%2 = OpExtInst %double %1 FClamp %double_0p2 %double_2 %double_4\n" +
2046 "OpReturn\n" +
2047 "OpFunctionEnd",
2048 2, 2.0),
2049 // Test case 18: FClamp 5.0 2.0 4.0
2050 InstructionFoldingCase<double>(
2051 Header() + "%main = OpFunction %void None %void_func\n" +
2052 "%main_lab = OpLabel\n" +
2053 "%2 = OpExtInst %double %1 FClamp %double_5 %double_2 %double_4\n" +
2054 "OpReturn\n" +
2055 "OpFunctionEnd",
2056 2, 4.0),
2057 // Test case 19: FClamp 1.0 2.0 x
2058 InstructionFoldingCase<double>(
2059 Header() + "%main = OpFunction %void None %void_func\n" +
2060 "%main_lab = OpLabel\n" +
2061 "%undef = OpUndef %double\n" +
2062 "%2 = OpExtInst %double %1 FClamp %double_1 %double_2 %undef\n" +
2063 "OpReturn\n" +
2064 "OpFunctionEnd",
2065 2, 2.0),
2066 // Test case 20: FClamp 1.0 x 0.5
2067 InstructionFoldingCase<double>(
2068 Header() + "%main = OpFunction %void None %void_func\n" +
2069 "%main_lab = OpLabel\n" +
2070 "%undef = OpUndef %double\n" +
2071 "%2 = OpExtInst %double %1 FClamp %double_1 %undef %double_0p5\n" +
2072 "OpReturn\n" +
2073 "OpFunctionEnd",
2074 2, 0.5),
2075 // Test case 21: Sqrt 4.0
2076 InstructionFoldingCase<double>(
2077 Header() + "%main = OpFunction %void None %void_func\n" +
2078 "%main_lab = OpLabel\n" +
2079 "%undef = OpUndef %double\n" +
2080 "%2 = OpExtInst %double %1 Sqrt %double_4\n" +
2081 "OpReturn\n" +
2082 "OpFunctionEnd",
2083 2, 2.0),
2084 // Test case 22: Pow 2.0 3.0
2085 InstructionFoldingCase<double>(
2086 Header() + "%main = OpFunction %void None %void_func\n" +
2087 "%main_lab = OpLabel\n" +
2088 "%undef = OpUndef %double\n" +
2089 "%2 = OpExtInst %double %1 Pow %double_2 %double_3\n" +
2090 "OpReturn\n" +
2091 "OpFunctionEnd",
2092 2, 8.0)
2093 ));
2094 // clang-format on
2095
2096 // clang-format off
2097 INSTANTIATE_TEST_SUITE_P(DoubleOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
2098 ::testing::Values(
2099 // Test case 0: fold 1.0 == 2.0
2100 InstructionFoldingCase<bool>(
2101 Header() + "%main = OpFunction %void None %void_func\n" +
2102 "%main_lab = OpLabel\n" +
2103 "%2 = OpFOrdEqual %bool %double_1 %double_2\n" +
2104 "OpReturn\n" +
2105 "OpFunctionEnd",
2106 2, false),
2107 // Test case 1: fold 1.0 != 2.0
2108 InstructionFoldingCase<bool>(
2109 Header() + "%main = OpFunction %void None %void_func\n" +
2110 "%main_lab = OpLabel\n" +
2111 "%2 = OpFOrdNotEqual %bool %double_1 %double_2\n" +
2112 "OpReturn\n" +
2113 "OpFunctionEnd",
2114 2, true),
2115 // Test case 2: fold 1.0 < 2.0
2116 InstructionFoldingCase<bool>(
2117 Header() + "%main = OpFunction %void None %void_func\n" +
2118 "%main_lab = OpLabel\n" +
2119 "%2 = OpFOrdLessThan %bool %double_1 %double_2\n" +
2120 "OpReturn\n" +
2121 "OpFunctionEnd",
2122 2, true),
2123 // Test case 3: fold 1.0 > 2.0
2124 InstructionFoldingCase<bool>(
2125 Header() + "%main = OpFunction %void None %void_func\n" +
2126 "%main_lab = OpLabel\n" +
2127 "%2 = OpFOrdGreaterThan %bool %double_1 %double_2\n" +
2128 "OpReturn\n" +
2129 "OpFunctionEnd",
2130 2, false),
2131 // Test case 4: fold 1.0 <= 2.0
2132 InstructionFoldingCase<bool>(
2133 Header() + "%main = OpFunction %void None %void_func\n" +
2134 "%main_lab = OpLabel\n" +
2135 "%2 = OpFOrdLessThanEqual %bool %double_1 %double_2\n" +
2136 "OpReturn\n" +
2137 "OpFunctionEnd",
2138 2, true),
2139 // Test case 5: fold 1.0 >= 2.0
2140 InstructionFoldingCase<bool>(
2141 Header() + "%main = OpFunction %void None %void_func\n" +
2142 "%main_lab = OpLabel\n" +
2143 "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_2\n" +
2144 "OpReturn\n" +
2145 "OpFunctionEnd",
2146 2, false),
2147 // Test case 6: fold 1.0 == 1.0
2148 InstructionFoldingCase<bool>(
2149 Header() + "%main = OpFunction %void None %void_func\n" +
2150 "%main_lab = OpLabel\n" +
2151 "%2 = OpFOrdEqual %bool %double_1 %double_1\n" +
2152 "OpReturn\n" +
2153 "OpFunctionEnd",
2154 2, true),
2155 // Test case 7: fold 1.0 != 1.0
2156 InstructionFoldingCase<bool>(
2157 Header() + "%main = OpFunction %void None %void_func\n" +
2158 "%main_lab = OpLabel\n" +
2159 "%2 = OpFOrdNotEqual %bool %double_1 %double_1\n" +
2160 "OpReturn\n" +
2161 "OpFunctionEnd",
2162 2, false),
2163 // Test case 8: fold 1.0 < 1.0
2164 InstructionFoldingCase<bool>(
2165 Header() + "%main = OpFunction %void None %void_func\n" +
2166 "%main_lab = OpLabel\n" +
2167 "%2 = OpFOrdLessThan %bool %double_1 %double_1\n" +
2168 "OpReturn\n" +
2169 "OpFunctionEnd",
2170 2, false),
2171 // Test case 9: fold 1.0 > 1.0
2172 InstructionFoldingCase<bool>(
2173 Header() + "%main = OpFunction %void None %void_func\n" +
2174 "%main_lab = OpLabel\n" +
2175 "%2 = OpFOrdGreaterThan %bool %double_1 %double_1\n" +
2176 "OpReturn\n" +
2177 "OpFunctionEnd",
2178 2, false),
2179 // Test case 10: fold 1.0 <= 1.0
2180 InstructionFoldingCase<bool>(
2181 Header() + "%main = OpFunction %void None %void_func\n" +
2182 "%main_lab = OpLabel\n" +
2183 "%2 = OpFOrdLessThanEqual %bool %double_1 %double_1\n" +
2184 "OpReturn\n" +
2185 "OpFunctionEnd",
2186 2, true),
2187 // Test case 11: fold 1.0 >= 1.0
2188 InstructionFoldingCase<bool>(
2189 Header() + "%main = OpFunction %void None %void_func\n" +
2190 "%main_lab = OpLabel\n" +
2191 "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_1\n" +
2192 "OpReturn\n" +
2193 "OpFunctionEnd",
2194 2, true),
2195 // Test case 12: fold 2.0 < 1.0
2196 InstructionFoldingCase<bool>(
2197 Header() + "%main = OpFunction %void None %void_func\n" +
2198 "%main_lab = OpLabel\n" +
2199 "%2 = OpFOrdLessThan %bool %double_2 %double_1\n" +
2200 "OpReturn\n" +
2201 "OpFunctionEnd",
2202 2, false),
2203 // Test case 13: fold 2.0 > 1.0
2204 InstructionFoldingCase<bool>(
2205 Header() + "%main = OpFunction %void None %void_func\n" +
2206 "%main_lab = OpLabel\n" +
2207 "%2 = OpFOrdGreaterThan %bool %double_2 %double_1\n" +
2208 "OpReturn\n" +
2209 "OpFunctionEnd",
2210 2, true),
2211 // Test case 14: fold 2.0 <= 1.0
2212 InstructionFoldingCase<bool>(
2213 Header() + "%main = OpFunction %void None %void_func\n" +
2214 "%main_lab = OpLabel\n" +
2215 "%2 = OpFOrdLessThanEqual %bool %double_2 %double_1\n" +
2216 "OpReturn\n" +
2217 "OpFunctionEnd",
2218 2, false),
2219 // Test case 15: fold 2.0 >= 1.0
2220 InstructionFoldingCase<bool>(
2221 Header() + "%main = OpFunction %void None %void_func\n" +
2222 "%main_lab = OpLabel\n" +
2223 "%2 = OpFOrdGreaterThanEqual %bool %double_2 %double_1\n" +
2224 "OpReturn\n" +
2225 "OpFunctionEnd",
2226 2, true)
2227 ));
2228
2229 INSTANTIATE_TEST_SUITE_P(DoubleUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
2230 ::testing::Values(
2231 // Test case 0: fold 1.0 == 2.0
2232 InstructionFoldingCase<bool>(
2233 Header() + "%main = OpFunction %void None %void_func\n" +
2234 "%main_lab = OpLabel\n" +
2235 "%2 = OpFUnordEqual %bool %double_1 %double_2\n" +
2236 "OpReturn\n" +
2237 "OpFunctionEnd",
2238 2, false),
2239 // Test case 1: fold 1.0 != 2.0
2240 InstructionFoldingCase<bool>(
2241 Header() + "%main = OpFunction %void None %void_func\n" +
2242 "%main_lab = OpLabel\n" +
2243 "%2 = OpFUnordNotEqual %bool %double_1 %double_2\n" +
2244 "OpReturn\n" +
2245 "OpFunctionEnd",
2246 2, true),
2247 // Test case 2: fold 1.0 < 2.0
2248 InstructionFoldingCase<bool>(
2249 Header() + "%main = OpFunction %void None %void_func\n" +
2250 "%main_lab = OpLabel\n" +
2251 "%2 = OpFUnordLessThan %bool %double_1 %double_2\n" +
2252 "OpReturn\n" +
2253 "OpFunctionEnd",
2254 2, true),
2255 // Test case 3: fold 1.0 > 2.0
2256 InstructionFoldingCase<bool>(
2257 Header() + "%main = OpFunction %void None %void_func\n" +
2258 "%main_lab = OpLabel\n" +
2259 "%2 = OpFUnordGreaterThan %bool %double_1 %double_2\n" +
2260 "OpReturn\n" +
2261 "OpFunctionEnd",
2262 2, false),
2263 // Test case 4: fold 1.0 <= 2.0
2264 InstructionFoldingCase<bool>(
2265 Header() + "%main = OpFunction %void None %void_func\n" +
2266 "%main_lab = OpLabel\n" +
2267 "%2 = OpFUnordLessThanEqual %bool %double_1 %double_2\n" +
2268 "OpReturn\n" +
2269 "OpFunctionEnd",
2270 2, true),
2271 // Test case 5: fold 1.0 >= 2.0
2272 InstructionFoldingCase<bool>(
2273 Header() + "%main = OpFunction %void None %void_func\n" +
2274 "%main_lab = OpLabel\n" +
2275 "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_2\n" +
2276 "OpReturn\n" +
2277 "OpFunctionEnd",
2278 2, false),
2279 // Test case 6: fold 1.0 == 1.0
2280 InstructionFoldingCase<bool>(
2281 Header() + "%main = OpFunction %void None %void_func\n" +
2282 "%main_lab = OpLabel\n" +
2283 "%2 = OpFUnordEqual %bool %double_1 %double_1\n" +
2284 "OpReturn\n" +
2285 "OpFunctionEnd",
2286 2, true),
2287 // Test case 7: fold 1.0 != 1.0
2288 InstructionFoldingCase<bool>(
2289 Header() + "%main = OpFunction %void None %void_func\n" +
2290 "%main_lab = OpLabel\n" +
2291 "%2 = OpFUnordNotEqual %bool %double_1 %double_1\n" +
2292 "OpReturn\n" +
2293 "OpFunctionEnd",
2294 2, false),
2295 // Test case 8: fold 1.0 < 1.0
2296 InstructionFoldingCase<bool>(
2297 Header() + "%main = OpFunction %void None %void_func\n" +
2298 "%main_lab = OpLabel\n" +
2299 "%2 = OpFUnordLessThan %bool %double_1 %double_1\n" +
2300 "OpReturn\n" +
2301 "OpFunctionEnd",
2302 2, false),
2303 // Test case 9: fold 1.0 > 1.0
2304 InstructionFoldingCase<bool>(
2305 Header() + "%main = OpFunction %void None %void_func\n" +
2306 "%main_lab = OpLabel\n" +
2307 "%2 = OpFUnordGreaterThan %bool %double_1 %double_1\n" +
2308 "OpReturn\n" +
2309 "OpFunctionEnd",
2310 2, false),
2311 // Test case 10: fold 1.0 <= 1.0
2312 InstructionFoldingCase<bool>(
2313 Header() + "%main = OpFunction %void None %void_func\n" +
2314 "%main_lab = OpLabel\n" +
2315 "%2 = OpFUnordLessThanEqual %bool %double_1 %double_1\n" +
2316 "OpReturn\n" +
2317 "OpFunctionEnd",
2318 2, true),
2319 // Test case 11: fold 1.0 >= 1.0
2320 InstructionFoldingCase<bool>(
2321 Header() + "%main = OpFunction %void None %void_func\n" +
2322 "%main_lab = OpLabel\n" +
2323 "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_1\n" +
2324 "OpReturn\n" +
2325 "OpFunctionEnd",
2326 2, true),
2327 // Test case 12: fold 2.0 < 1.0
2328 InstructionFoldingCase<bool>(
2329 Header() + "%main = OpFunction %void None %void_func\n" +
2330 "%main_lab = OpLabel\n" +
2331 "%2 = OpFUnordLessThan %bool %double_2 %double_1\n" +
2332 "OpReturn\n" +
2333 "OpFunctionEnd",
2334 2, false),
2335 // Test case 13: fold 2.0 > 1.0
2336 InstructionFoldingCase<bool>(
2337 Header() + "%main = OpFunction %void None %void_func\n" +
2338 "%main_lab = OpLabel\n" +
2339 "%2 = OpFUnordGreaterThan %bool %double_2 %double_1\n" +
2340 "OpReturn\n" +
2341 "OpFunctionEnd",
2342 2, true),
2343 // Test case 14: fold 2.0 <= 1.0
2344 InstructionFoldingCase<bool>(
2345 Header() + "%main = OpFunction %void None %void_func\n" +
2346 "%main_lab = OpLabel\n" +
2347 "%2 = OpFUnordLessThanEqual %bool %double_2 %double_1\n" +
2348 "OpReturn\n" +
2349 "OpFunctionEnd",
2350 2, false),
2351 // Test case 15: fold 2.0 >= 1.0
2352 InstructionFoldingCase<bool>(
2353 Header() + "%main = OpFunction %void None %void_func\n" +
2354 "%main_lab = OpLabel\n" +
2355 "%2 = OpFUnordGreaterThanEqual %bool %double_2 %double_1\n" +
2356 "OpReturn\n" +
2357 "OpFunctionEnd",
2358 2, true)
2359 ));
2360
2361 INSTANTIATE_TEST_SUITE_P(FloatOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
2362 ::testing::Values(
2363 // Test case 0: fold 1.0 == 2.0
2364 InstructionFoldingCase<bool>(
2365 Header() + "%main = OpFunction %void None %void_func\n" +
2366 "%main_lab = OpLabel\n" +
2367 "%2 = OpFOrdEqual %bool %float_1 %float_2\n" +
2368 "OpReturn\n" +
2369 "OpFunctionEnd",
2370 2, false),
2371 // Test case 1: fold 1.0 != 2.0
2372 InstructionFoldingCase<bool>(
2373 Header() + "%main = OpFunction %void None %void_func\n" +
2374 "%main_lab = OpLabel\n" +
2375 "%2 = OpFOrdNotEqual %bool %float_1 %float_2\n" +
2376 "OpReturn\n" +
2377 "OpFunctionEnd",
2378 2, true),
2379 // Test case 2: fold 1.0 < 2.0
2380 InstructionFoldingCase<bool>(
2381 Header() + "%main = OpFunction %void None %void_func\n" +
2382 "%main_lab = OpLabel\n" +
2383 "%2 = OpFOrdLessThan %bool %float_1 %float_2\n" +
2384 "OpReturn\n" +
2385 "OpFunctionEnd",
2386 2, true),
2387 // Test case 3: fold 1.0 > 2.0
2388 InstructionFoldingCase<bool>(
2389 Header() + "%main = OpFunction %void None %void_func\n" +
2390 "%main_lab = OpLabel\n" +
2391 "%2 = OpFOrdGreaterThan %bool %float_1 %float_2\n" +
2392 "OpReturn\n" +
2393 "OpFunctionEnd",
2394 2, false),
2395 // Test case 4: fold 1.0 <= 2.0
2396 InstructionFoldingCase<bool>(
2397 Header() + "%main = OpFunction %void None %void_func\n" +
2398 "%main_lab = OpLabel\n" +
2399 "%2 = OpFOrdLessThanEqual %bool %float_1 %float_2\n" +
2400 "OpReturn\n" +
2401 "OpFunctionEnd",
2402 2, true),
2403 // Test case 5: fold 1.0 >= 2.0
2404 InstructionFoldingCase<bool>(
2405 Header() + "%main = OpFunction %void None %void_func\n" +
2406 "%main_lab = OpLabel\n" +
2407 "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_2\n" +
2408 "OpReturn\n" +
2409 "OpFunctionEnd",
2410 2, false),
2411 // Test case 6: fold 1.0 == 1.0
2412 InstructionFoldingCase<bool>(
2413 Header() + "%main = OpFunction %void None %void_func\n" +
2414 "%main_lab = OpLabel\n" +
2415 "%2 = OpFOrdEqual %bool %float_1 %float_1\n" +
2416 "OpReturn\n" +
2417 "OpFunctionEnd",
2418 2, true),
2419 // Test case 7: fold 1.0 != 1.0
2420 InstructionFoldingCase<bool>(
2421 Header() + "%main = OpFunction %void None %void_func\n" +
2422 "%main_lab = OpLabel\n" +
2423 "%2 = OpFOrdNotEqual %bool %float_1 %float_1\n" +
2424 "OpReturn\n" +
2425 "OpFunctionEnd",
2426 2, false),
2427 // Test case 8: fold 1.0 < 1.0
2428 InstructionFoldingCase<bool>(
2429 Header() + "%main = OpFunction %void None %void_func\n" +
2430 "%main_lab = OpLabel\n" +
2431 "%2 = OpFOrdLessThan %bool %float_1 %float_1\n" +
2432 "OpReturn\n" +
2433 "OpFunctionEnd",
2434 2, false),
2435 // Test case 9: fold 1.0 > 1.0
2436 InstructionFoldingCase<bool>(
2437 Header() + "%main = OpFunction %void None %void_func\n" +
2438 "%main_lab = OpLabel\n" +
2439 "%2 = OpFOrdGreaterThan %bool %float_1 %float_1\n" +
2440 "OpReturn\n" +
2441 "OpFunctionEnd",
2442 2, false),
2443 // Test case 10: fold 1.0 <= 1.0
2444 InstructionFoldingCase<bool>(
2445 Header() + "%main = OpFunction %void None %void_func\n" +
2446 "%main_lab = OpLabel\n" +
2447 "%2 = OpFOrdLessThanEqual %bool %float_1 %float_1\n" +
2448 "OpReturn\n" +
2449 "OpFunctionEnd",
2450 2, true),
2451 // Test case 11: fold 1.0 >= 1.0
2452 InstructionFoldingCase<bool>(
2453 Header() + "%main = OpFunction %void None %void_func\n" +
2454 "%main_lab = OpLabel\n" +
2455 "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_1\n" +
2456 "OpReturn\n" +
2457 "OpFunctionEnd",
2458 2, true),
2459 // Test case 12: fold 2.0 < 1.0
2460 InstructionFoldingCase<bool>(
2461 Header() + "%main = OpFunction %void None %void_func\n" +
2462 "%main_lab = OpLabel\n" +
2463 "%2 = OpFOrdLessThan %bool %float_2 %float_1\n" +
2464 "OpReturn\n" +
2465 "OpFunctionEnd",
2466 2, false),
2467 // Test case 13: fold 2.0 > 1.0
2468 InstructionFoldingCase<bool>(
2469 Header() + "%main = OpFunction %void None %void_func\n" +
2470 "%main_lab = OpLabel\n" +
2471 "%2 = OpFOrdGreaterThan %bool %float_2 %float_1\n" +
2472 "OpReturn\n" +
2473 "OpFunctionEnd",
2474 2, true),
2475 // Test case 14: fold 2.0 <= 1.0
2476 InstructionFoldingCase<bool>(
2477 Header() + "%main = OpFunction %void None %void_func\n" +
2478 "%main_lab = OpLabel\n" +
2479 "%2 = OpFOrdLessThanEqual %bool %float_2 %float_1\n" +
2480 "OpReturn\n" +
2481 "OpFunctionEnd",
2482 2, false),
2483 // Test case 15: fold 2.0 >= 1.0
2484 InstructionFoldingCase<bool>(
2485 Header() + "%main = OpFunction %void None %void_func\n" +
2486 "%main_lab = OpLabel\n" +
2487 "%2 = OpFOrdGreaterThanEqual %bool %float_2 %float_1\n" +
2488 "OpReturn\n" +
2489 "OpFunctionEnd",
2490 2, true)
2491 ));
2492
2493 INSTANTIATE_TEST_SUITE_P(FloatUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
2494 ::testing::Values(
2495 // Test case 0: fold 1.0 == 2.0
2496 InstructionFoldingCase<bool>(
2497 Header() + "%main = OpFunction %void None %void_func\n" +
2498 "%main_lab = OpLabel\n" +
2499 "%2 = OpFUnordEqual %bool %float_1 %float_2\n" +
2500 "OpReturn\n" +
2501 "OpFunctionEnd",
2502 2, false),
2503 // Test case 1: fold 1.0 != 2.0
2504 InstructionFoldingCase<bool>(
2505 Header() + "%main = OpFunction %void None %void_func\n" +
2506 "%main_lab = OpLabel\n" +
2507 "%2 = OpFUnordNotEqual %bool %float_1 %float_2\n" +
2508 "OpReturn\n" +
2509 "OpFunctionEnd",
2510 2, true),
2511 // Test case 2: fold 1.0 < 2.0
2512 InstructionFoldingCase<bool>(
2513 Header() + "%main = OpFunction %void None %void_func\n" +
2514 "%main_lab = OpLabel\n" +
2515 "%2 = OpFUnordLessThan %bool %float_1 %float_2\n" +
2516 "OpReturn\n" +
2517 "OpFunctionEnd",
2518 2, true),
2519 // Test case 3: fold 1.0 > 2.0
2520 InstructionFoldingCase<bool>(
2521 Header() + "%main = OpFunction %void None %void_func\n" +
2522 "%main_lab = OpLabel\n" +
2523 "%2 = OpFUnordGreaterThan %bool %float_1 %float_2\n" +
2524 "OpReturn\n" +
2525 "OpFunctionEnd",
2526 2, false),
2527 // Test case 4: fold 1.0 <= 2.0
2528 InstructionFoldingCase<bool>(
2529 Header() + "%main = OpFunction %void None %void_func\n" +
2530 "%main_lab = OpLabel\n" +
2531 "%2 = OpFUnordLessThanEqual %bool %float_1 %float_2\n" +
2532 "OpReturn\n" +
2533 "OpFunctionEnd",
2534 2, true),
2535 // Test case 5: fold 1.0 >= 2.0
2536 InstructionFoldingCase<bool>(
2537 Header() + "%main = OpFunction %void None %void_func\n" +
2538 "%main_lab = OpLabel\n" +
2539 "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_2\n" +
2540 "OpReturn\n" +
2541 "OpFunctionEnd",
2542 2, false),
2543 // Test case 6: fold 1.0 == 1.0
2544 InstructionFoldingCase<bool>(
2545 Header() + "%main = OpFunction %void None %void_func\n" +
2546 "%main_lab = OpLabel\n" +
2547 "%2 = OpFUnordEqual %bool %float_1 %float_1\n" +
2548 "OpReturn\n" +
2549 "OpFunctionEnd",
2550 2, true),
2551 // Test case 7: fold 1.0 != 1.0
2552 InstructionFoldingCase<bool>(
2553 Header() + "%main = OpFunction %void None %void_func\n" +
2554 "%main_lab = OpLabel\n" +
2555 "%2 = OpFUnordNotEqual %bool %float_1 %float_1\n" +
2556 "OpReturn\n" +
2557 "OpFunctionEnd",
2558 2, false),
2559 // Test case 8: fold 1.0 < 1.0
2560 InstructionFoldingCase<bool>(
2561 Header() + "%main = OpFunction %void None %void_func\n" +
2562 "%main_lab = OpLabel\n" +
2563 "%2 = OpFUnordLessThan %bool %float_1 %float_1\n" +
2564 "OpReturn\n" +
2565 "OpFunctionEnd",
2566 2, false),
2567 // Test case 9: fold 1.0 > 1.0
2568 InstructionFoldingCase<bool>(
2569 Header() + "%main = OpFunction %void None %void_func\n" +
2570 "%main_lab = OpLabel\n" +
2571 "%2 = OpFUnordGreaterThan %bool %float_1 %float_1\n" +
2572 "OpReturn\n" +
2573 "OpFunctionEnd",
2574 2, false),
2575 // Test case 10: fold 1.0 <= 1.0
2576 InstructionFoldingCase<bool>(
2577 Header() + "%main = OpFunction %void None %void_func\n" +
2578 "%main_lab = OpLabel\n" +
2579 "%2 = OpFUnordLessThanEqual %bool %float_1 %float_1\n" +
2580 "OpReturn\n" +
2581 "OpFunctionEnd",
2582 2, true),
2583 // Test case 11: fold 1.0 >= 1.0
2584 InstructionFoldingCase<bool>(
2585 Header() + "%main = OpFunction %void None %void_func\n" +
2586 "%main_lab = OpLabel\n" +
2587 "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_1\n" +
2588 "OpReturn\n" +
2589 "OpFunctionEnd",
2590 2, true),
2591 // Test case 12: fold 2.0 < 1.0
2592 InstructionFoldingCase<bool>(
2593 Header() + "%main = OpFunction %void None %void_func\n" +
2594 "%main_lab = OpLabel\n" +
2595 "%2 = OpFUnordLessThan %bool %float_2 %float_1\n" +
2596 "OpReturn\n" +
2597 "OpFunctionEnd",
2598 2, false),
2599 // Test case 13: fold 2.0 > 1.0
2600 InstructionFoldingCase<bool>(
2601 Header() + "%main = OpFunction %void None %void_func\n" +
2602 "%main_lab = OpLabel\n" +
2603 "%2 = OpFUnordGreaterThan %bool %float_2 %float_1\n" +
2604 "OpReturn\n" +
2605 "OpFunctionEnd",
2606 2, true),
2607 // Test case 14: fold 2.0 <= 1.0
2608 InstructionFoldingCase<bool>(
2609 Header() + "%main = OpFunction %void None %void_func\n" +
2610 "%main_lab = OpLabel\n" +
2611 "%2 = OpFUnordLessThanEqual %bool %float_2 %float_1\n" +
2612 "OpReturn\n" +
2613 "OpFunctionEnd",
2614 2, false),
2615 // Test case 15: fold 2.0 >= 1.0
2616 InstructionFoldingCase<bool>(
2617 Header() + "%main = OpFunction %void None %void_func\n" +
2618 "%main_lab = OpLabel\n" +
2619 "%2 = OpFUnordGreaterThanEqual %bool %float_2 %float_1\n" +
2620 "OpReturn\n" +
2621 "OpFunctionEnd",
2622 2, true)
2623 ));
2624
2625 INSTANTIATE_TEST_SUITE_P(DoubleNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
2626 ::testing::Values(
2627 // Test case 0: fold NaN == 0 (ord)
2628 InstructionFoldingCase<bool>(
2629 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2630 "%main_lab = OpLabel\n" +
2631 "%2 = OpFOrdEqual %bool %double_nan %double_0\n" +
2632 "OpReturn\n" +
2633 "OpFunctionEnd",
2634 2, false),
2635 // Test case 1: fold NaN == NaN (unord)
2636 InstructionFoldingCase<bool>(
2637 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2638 "%main_lab = OpLabel\n" +
2639 "%2 = OpFUnordEqual %bool %double_nan %double_0\n" +
2640 "OpReturn\n" +
2641 "OpFunctionEnd",
2642 2, true),
2643 // Test case 2: fold NaN != NaN (ord)
2644 InstructionFoldingCase<bool>(
2645 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2646 "%main_lab = OpLabel\n" +
2647 "%2 = OpFOrdNotEqual %bool %double_nan %double_0\n" +
2648 "OpReturn\n" +
2649 "OpFunctionEnd",
2650 2, false),
2651 // Test case 3: fold NaN != NaN (unord)
2652 InstructionFoldingCase<bool>(
2653 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2654 "%main_lab = OpLabel\n" +
2655 "%2 = OpFUnordNotEqual %bool %double_nan %double_0\n" +
2656 "OpReturn\n" +
2657 "OpFunctionEnd",
2658 2, true)
2659 ));
2660
2661 INSTANTIATE_TEST_SUITE_P(FloatNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
2662 ::testing::Values(
2663 // Test case 0: fold NaN == 0 (ord)
2664 InstructionFoldingCase<bool>(
2665 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2666 "%main_lab = OpLabel\n" +
2667 "%2 = OpFOrdEqual %bool %float_nan %float_0\n" +
2668 "OpReturn\n" +
2669 "OpFunctionEnd",
2670 2, false),
2671 // Test case 1: fold NaN == NaN (unord)
2672 InstructionFoldingCase<bool>(
2673 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2674 "%main_lab = OpLabel\n" +
2675 "%2 = OpFUnordEqual %bool %float_nan %float_0\n" +
2676 "OpReturn\n" +
2677 "OpFunctionEnd",
2678 2, true),
2679 // Test case 2: fold NaN != NaN (ord)
2680 InstructionFoldingCase<bool>(
2681 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2682 "%main_lab = OpLabel\n" +
2683 "%2 = OpFOrdNotEqual %bool %float_nan %float_0\n" +
2684 "OpReturn\n" +
2685 "OpFunctionEnd",
2686 2, false),
2687 // Test case 3: fold NaN != NaN (unord)
2688 InstructionFoldingCase<bool>(
2689 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2690 "%main_lab = OpLabel\n" +
2691 "%2 = OpFUnordNotEqual %bool %float_nan %float_0\n" +
2692 "OpReturn\n" +
2693 "OpFunctionEnd",
2694 2, true)
2695 ));
2696 // clang-format on
2697
2698 template <class ResultType>
2699 struct InstructionFoldingCaseWithMap {
InstructionFoldingCaseWithMapspvtools::opt::__anona22e47290111::InstructionFoldingCaseWithMap2700 InstructionFoldingCaseWithMap(const std::string& tb, uint32_t id,
2701 ResultType result,
2702 std::function<uint32_t(uint32_t)> map)
2703 : test_body(tb), id_to_fold(id), expected_result(result), id_map(map) {}
2704
2705 std::string test_body;
2706 uint32_t id_to_fold;
2707 ResultType expected_result;
2708 std::function<uint32_t(uint32_t)> id_map;
2709 };
2710
2711 using IntegerInstructionFoldingTestWithMap =
2712 ::testing::TestWithParam<InstructionFoldingCaseWithMap<uint32_t>>;
2713
TEST_P(IntegerInstructionFoldingTestWithMap,Case)2714 TEST_P(IntegerInstructionFoldingTestWithMap, Case) {
2715 const auto& tc = GetParam();
2716
2717 // Build module.
2718 std::unique_ptr<IRContext> context =
2719 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
2720 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2721 ASSERT_NE(nullptr, context);
2722
2723 // Fold the instruction to test.
2724 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
2725 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
2726 inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
2727 tc.id_map);
2728
2729 // Make sure the instruction folded as expected.
2730 EXPECT_NE(inst, nullptr);
2731 if (inst != nullptr) {
2732 EXPECT_EQ(inst->opcode(), SpvOpConstant);
2733 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
2734 const analysis::IntConstant* result =
2735 const_mrg->GetConstantFromInst(inst)->AsIntConstant();
2736 EXPECT_NE(result, nullptr);
2737 if (result != nullptr) {
2738 EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
2739 }
2740 }
2741 }
2742 // clang-format off
2743 INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTestWithMap,
2744 ::testing::Values(
2745 // Test case 0: fold %3 = 0; %3 * n
2746 InstructionFoldingCaseWithMap<uint32_t>(
2747 Header() + "%main = OpFunction %void None %void_func\n" +
2748 "%main_lab = OpLabel\n" +
2749 "%n = OpVariable %_ptr_int Function\n" +
2750 "%load = OpLoad %int %n\n" +
2751 "%3 = OpCopyObject %int %int_0\n"
2752 "%2 = OpIMul %int %3 %load\n" +
2753 "OpReturn\n" +
2754 "OpFunctionEnd",
__anona22e47290202(uint32_t id) 2755 2, 0, [](uint32_t id) {return (id == 3 ? INT_0_ID : id);})
2756 ));
2757 // clang-format on
2758
2759 using BooleanInstructionFoldingTestWithMap =
2760 ::testing::TestWithParam<InstructionFoldingCaseWithMap<bool>>;
2761
TEST_P(BooleanInstructionFoldingTestWithMap,Case)2762 TEST_P(BooleanInstructionFoldingTestWithMap, Case) {
2763 const auto& tc = GetParam();
2764
2765 // Build module.
2766 std::unique_ptr<IRContext> context =
2767 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
2768 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2769 ASSERT_NE(nullptr, context);
2770
2771 // Fold the instruction to test.
2772 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
2773 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
2774 inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
2775 tc.id_map);
2776
2777 // Make sure the instruction folded as expected.
2778 EXPECT_NE(inst, nullptr);
2779 if (inst != nullptr) {
2780 std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
2781 EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
2782 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
2783 const analysis::BoolConstant* result =
2784 const_mrg->GetConstantFromInst(inst)->AsBoolConstant();
2785 EXPECT_NE(result, nullptr);
2786 if (result != nullptr) {
2787 EXPECT_EQ(result->value(), tc.expected_result);
2788 }
2789 }
2790 }
2791
2792 // clang-format off
2793 INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTestWithMap,
2794 ::testing::Values(
2795 // Test case 0: fold %3 = true; %3 || n
2796 InstructionFoldingCaseWithMap<bool>(
2797 Header() + "%main = OpFunction %void None %void_func\n" +
2798 "%main_lab = OpLabel\n" +
2799 "%n = OpVariable %_ptr_bool Function\n" +
2800 "%load = OpLoad %bool %n\n" +
2801 "%3 = OpCopyObject %bool %true\n" +
2802 "%2 = OpLogicalOr %bool %3 %load\n" +
2803 "OpReturn\n" +
2804 "OpFunctionEnd",
__anona22e47290302(uint32_t id) 2805 2, true, [](uint32_t id) {return (id == 3 ? TRUE_ID : id);})
2806 ));
2807 // clang-format on
2808
2809 using GeneralInstructionFoldingTest =
2810 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
2811
TEST_P(GeneralInstructionFoldingTest,Case)2812 TEST_P(GeneralInstructionFoldingTest, Case) {
2813 const auto& tc = GetParam();
2814
2815 // Build module.
2816 std::unique_ptr<IRContext> context =
2817 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
2818 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2819 ASSERT_NE(nullptr, context);
2820
2821 // Fold the instruction to test.
2822 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
2823 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
2824 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
2825 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
2826
2827 // Make sure the instruction folded as expected.
2828 EXPECT_EQ(inst->result_id(), original_inst->result_id());
2829 EXPECT_EQ(inst->type_id(), original_inst->type_id());
2830 EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
2831 if (succeeded) {
2832 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
2833 EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
2834 } else {
2835 EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
2836 for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
2837 EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
2838 }
2839 }
2840 }
2841
2842 // clang-format off
2843 INSTANTIATE_TEST_SUITE_P(IntegerArithmeticTestCases, GeneralInstructionFoldingTest,
2844 ::testing::Values(
2845 // Test case 0: Don't fold n * m
2846 InstructionFoldingCase<uint32_t>(
2847 Header() + "%main = OpFunction %void None %void_func\n" +
2848 "%main_lab = OpLabel\n" +
2849 "%n = OpVariable %_ptr_int Function\n" +
2850 "%m = OpVariable %_ptr_int Function\n" +
2851 "%load_n = OpLoad %int %n\n" +
2852 "%load_m = OpLoad %int %m\n" +
2853 "%2 = OpIMul %int %load_n %load_m\n" +
2854 "OpReturn\n" +
2855 "OpFunctionEnd",
2856 2, 0),
2857 // Test case 1: Don't fold n / m (unsigned)
2858 InstructionFoldingCase<uint32_t>(
2859 Header() + "%main = OpFunction %void None %void_func\n" +
2860 "%main_lab = OpLabel\n" +
2861 "%n = OpVariable %_ptr_uint Function\n" +
2862 "%m = OpVariable %_ptr_uint Function\n" +
2863 "%load_n = OpLoad %uint %n\n" +
2864 "%load_m = OpLoad %uint %m\n" +
2865 "%2 = OpUDiv %uint %load_n %load_m\n" +
2866 "OpReturn\n" +
2867 "OpFunctionEnd",
2868 2, 0),
2869 // Test case 2: Don't fold n / m (signed)
2870 InstructionFoldingCase<uint32_t>(
2871 Header() + "%main = OpFunction %void None %void_func\n" +
2872 "%main_lab = OpLabel\n" +
2873 "%n = OpVariable %_ptr_int Function\n" +
2874 "%m = OpVariable %_ptr_int Function\n" +
2875 "%load_n = OpLoad %int %n\n" +
2876 "%load_m = OpLoad %int %m\n" +
2877 "%2 = OpSDiv %int %load_n %load_m\n" +
2878 "OpReturn\n" +
2879 "OpFunctionEnd",
2880 2, 0),
2881 // Test case 3: Don't fold n remainder m
2882 InstructionFoldingCase<uint32_t>(
2883 Header() + "%main = OpFunction %void None %void_func\n" +
2884 "%main_lab = OpLabel\n" +
2885 "%n = OpVariable %_ptr_int Function\n" +
2886 "%m = OpVariable %_ptr_int Function\n" +
2887 "%load_n = OpLoad %int %n\n" +
2888 "%load_m = OpLoad %int %m\n" +
2889 "%2 = OpSRem %int %load_n %load_m\n" +
2890 "OpReturn\n" +
2891 "OpFunctionEnd",
2892 2, 0),
2893 // Test case 4: Don't fold n % m (signed)
2894 InstructionFoldingCase<uint32_t>(
2895 Header() + "%main = OpFunction %void None %void_func\n" +
2896 "%main_lab = OpLabel\n" +
2897 "%n = OpVariable %_ptr_int Function\n" +
2898 "%m = OpVariable %_ptr_int Function\n" +
2899 "%load_n = OpLoad %int %n\n" +
2900 "%load_m = OpLoad %int %m\n" +
2901 "%2 = OpSMod %int %load_n %load_m\n" +
2902 "OpReturn\n" +
2903 "OpFunctionEnd",
2904 2, 0),
2905 // Test case 5: Don't fold n % m (unsigned)
2906 InstructionFoldingCase<uint32_t>(
2907 Header() + "%main = OpFunction %void None %void_func\n" +
2908 "%main_lab = OpLabel\n" +
2909 "%n = OpVariable %_ptr_uint Function\n" +
2910 "%m = OpVariable %_ptr_uint Function\n" +
2911 "%load_n = OpLoad %uint %n\n" +
2912 "%load_m = OpLoad %uint %m\n" +
2913 "%2 = OpUMod %int %load_n %load_m\n" +
2914 "OpReturn\n" +
2915 "OpFunctionEnd",
2916 2, 0),
2917 // Test case 6: Don't fold n << m
2918 InstructionFoldingCase<uint32_t>(
2919 Header() + "%main = OpFunction %void None %void_func\n" +
2920 "%main_lab = OpLabel\n" +
2921 "%n = OpVariable %_ptr_uint Function\n" +
2922 "%m = OpVariable %_ptr_uint Function\n" +
2923 "%load_n = OpLoad %uint %n\n" +
2924 "%load_m = OpLoad %uint %m\n" +
2925 "%2 = OpShiftRightLogical %int %load_n %load_m\n" +
2926 "OpReturn\n" +
2927 "OpFunctionEnd",
2928 2, 0),
2929 // Test case 7: Don't fold n >> m
2930 InstructionFoldingCase<uint32_t>(
2931 Header() + "%main = OpFunction %void None %void_func\n" +
2932 "%main_lab = OpLabel\n" +
2933 "%n = OpVariable %_ptr_uint Function\n" +
2934 "%m = OpVariable %_ptr_uint Function\n" +
2935 "%load_n = OpLoad %uint %n\n" +
2936 "%load_m = OpLoad %uint %m\n" +
2937 "%2 = OpShiftLeftLogical %int %load_n %load_m\n" +
2938 "OpReturn\n" +
2939 "OpFunctionEnd",
2940 2, 0),
2941 // Test case 8: Don't fold n | m
2942 InstructionFoldingCase<uint32_t>(
2943 Header() + "%main = OpFunction %void None %void_func\n" +
2944 "%main_lab = OpLabel\n" +
2945 "%n = OpVariable %_ptr_uint Function\n" +
2946 "%m = OpVariable %_ptr_uint Function\n" +
2947 "%load_n = OpLoad %uint %n\n" +
2948 "%load_m = OpLoad %uint %m\n" +
2949 "%2 = OpBitwiseOr %int %load_n %load_m\n" +
2950 "OpReturn\n" +
2951 "OpFunctionEnd",
2952 2, 0),
2953 // Test case 9: Don't fold n & m
2954 InstructionFoldingCase<uint32_t>(
2955 Header() + "%main = OpFunction %void None %void_func\n" +
2956 "%main_lab = OpLabel\n" +
2957 "%n = OpVariable %_ptr_uint Function\n" +
2958 "%m = OpVariable %_ptr_uint Function\n" +
2959 "%load_n = OpLoad %uint %n\n" +
2960 "%load_m = OpLoad %uint %m\n" +
2961 "%2 = OpBitwiseAnd %int %load_n %load_m\n" +
2962 "OpReturn\n" +
2963 "OpFunctionEnd",
2964 2, 0),
2965 // Test case 10: Don't fold n < m (unsigned)
2966 InstructionFoldingCase<uint32_t>(
2967 Header() + "%main = OpFunction %void None %void_func\n" +
2968 "%main_lab = OpLabel\n" +
2969 "%n = OpVariable %_ptr_uint Function\n" +
2970 "%m = OpVariable %_ptr_uint Function\n" +
2971 "%load_n = OpLoad %uint %n\n" +
2972 "%load_m = OpLoad %uint %m\n" +
2973 "%2 = OpULessThan %bool %load_n %load_m\n" +
2974 "OpReturn\n" +
2975 "OpFunctionEnd",
2976 2, 0),
2977 // Test case 11: Don't fold n > m (unsigned)
2978 InstructionFoldingCase<uint32_t>(
2979 Header() + "%main = OpFunction %void None %void_func\n" +
2980 "%main_lab = OpLabel\n" +
2981 "%n = OpVariable %_ptr_uint Function\n" +
2982 "%m = OpVariable %_ptr_uint Function\n" +
2983 "%load_n = OpLoad %uint %n\n" +
2984 "%load_m = OpLoad %uint %m\n" +
2985 "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
2986 "OpReturn\n" +
2987 "OpFunctionEnd",
2988 2, 0),
2989 // Test case 12: Don't fold n <= m (unsigned)
2990 InstructionFoldingCase<uint32_t>(
2991 Header() + "%main = OpFunction %void None %void_func\n" +
2992 "%main_lab = OpLabel\n" +
2993 "%n = OpVariable %_ptr_uint Function\n" +
2994 "%m = OpVariable %_ptr_uint Function\n" +
2995 "%load_n = OpLoad %uint %n\n" +
2996 "%load_m = OpLoad %uint %m\n" +
2997 "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
2998 "OpReturn\n" +
2999 "OpFunctionEnd",
3000 2, 0),
3001 // Test case 13: Don't fold n >= m (unsigned)
3002 InstructionFoldingCase<uint32_t>(
3003 Header() + "%main = OpFunction %void None %void_func\n" +
3004 "%main_lab = OpLabel\n" +
3005 "%n = OpVariable %_ptr_uint Function\n" +
3006 "%m = OpVariable %_ptr_uint Function\n" +
3007 "%load_n = OpLoad %uint %n\n" +
3008 "%load_m = OpLoad %uint %m\n" +
3009 "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
3010 "OpReturn\n" +
3011 "OpFunctionEnd",
3012 2, 0),
3013 // Test case 14: Don't fold n < m (signed)
3014 InstructionFoldingCase<uint32_t>(
3015 Header() + "%main = OpFunction %void None %void_func\n" +
3016 "%main_lab = OpLabel\n" +
3017 "%n = OpVariable %_ptr_int Function\n" +
3018 "%m = OpVariable %_ptr_int Function\n" +
3019 "%load_n = OpLoad %int %n\n" +
3020 "%load_m = OpLoad %int %m\n" +
3021 "%2 = OpULessThan %bool %load_n %load_m\n" +
3022 "OpReturn\n" +
3023 "OpFunctionEnd",
3024 2, 0),
3025 // Test case 15: Don't fold n > m (signed)
3026 InstructionFoldingCase<uint32_t>(
3027 Header() + "%main = OpFunction %void None %void_func\n" +
3028 "%main_lab = OpLabel\n" +
3029 "%n = OpVariable %_ptr_int Function\n" +
3030 "%m = OpVariable %_ptr_int Function\n" +
3031 "%load_n = OpLoad %int %n\n" +
3032 "%load_m = OpLoad %int %m\n" +
3033 "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
3034 "OpReturn\n" +
3035 "OpFunctionEnd",
3036 2, 0),
3037 // Test case 16: Don't fold n <= m (signed)
3038 InstructionFoldingCase<uint32_t>(
3039 Header() + "%main = OpFunction %void None %void_func\n" +
3040 "%main_lab = OpLabel\n" +
3041 "%n = OpVariable %_ptr_int Function\n" +
3042 "%m = OpVariable %_ptr_int Function\n" +
3043 "%load_n = OpLoad %int %n\n" +
3044 "%load_m = OpLoad %int %m\n" +
3045 "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
3046 "OpReturn\n" +
3047 "OpFunctionEnd",
3048 2, 0),
3049 // Test case 17: Don't fold n >= m (signed)
3050 InstructionFoldingCase<uint32_t>(
3051 Header() + "%main = OpFunction %void None %void_func\n" +
3052 "%main_lab = OpLabel\n" +
3053 "%n = OpVariable %_ptr_int Function\n" +
3054 "%m = OpVariable %_ptr_int Function\n" +
3055 "%load_n = OpLoad %int %n\n" +
3056 "%load_m = OpLoad %int %m\n" +
3057 "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
3058 "OpReturn\n" +
3059 "OpFunctionEnd",
3060 2, 0),
3061 // Test case 18: Don't fold n || m
3062 InstructionFoldingCase<uint32_t>(
3063 Header() + "%main = OpFunction %void None %void_func\n" +
3064 "%main_lab = OpLabel\n" +
3065 "%n = OpVariable %_ptr_bool Function\n" +
3066 "%m = OpVariable %_ptr_bool Function\n" +
3067 "%load_n = OpLoad %bool %n\n" +
3068 "%load_m = OpLoad %bool %m\n" +
3069 "%2 = OpLogicalOr %bool %load_n %load_m\n" +
3070 "OpReturn\n" +
3071 "OpFunctionEnd",
3072 2, 0),
3073 // Test case 19: Don't fold n && m
3074 InstructionFoldingCase<uint32_t>(
3075 Header() + "%main = OpFunction %void None %void_func\n" +
3076 "%main_lab = OpLabel\n" +
3077 "%n = OpVariable %_ptr_bool Function\n" +
3078 "%m = OpVariable %_ptr_bool Function\n" +
3079 "%load_n = OpLoad %bool %n\n" +
3080 "%load_m = OpLoad %bool %m\n" +
3081 "%2 = OpLogicalAnd %bool %load_n %load_m\n" +
3082 "OpReturn\n" +
3083 "OpFunctionEnd",
3084 2, 0),
3085 // Test case 20: Don't fold n * 3
3086 InstructionFoldingCase<uint32_t>(
3087 Header() + "%main = OpFunction %void None %void_func\n" +
3088 "%main_lab = OpLabel\n" +
3089 "%n = OpVariable %_ptr_int Function\n" +
3090 "%load_n = OpLoad %int %n\n" +
3091 "%2 = OpIMul %int %load_n %int_3\n" +
3092 "OpReturn\n" +
3093 "OpFunctionEnd",
3094 2, 0),
3095 // Test case 21: Don't fold n / 3 (unsigned)
3096 InstructionFoldingCase<uint32_t>(
3097 Header() + "%main = OpFunction %void None %void_func\n" +
3098 "%main_lab = OpLabel\n" +
3099 "%n = OpVariable %_ptr_uint Function\n" +
3100 "%load_n = OpLoad %uint %n\n" +
3101 "%2 = OpUDiv %uint %load_n %uint_3\n" +
3102 "OpReturn\n" +
3103 "OpFunctionEnd",
3104 2, 0),
3105 // Test case 22: Don't fold n / 3 (signed)
3106 InstructionFoldingCase<uint32_t>(
3107 Header() + "%main = OpFunction %void None %void_func\n" +
3108 "%main_lab = OpLabel\n" +
3109 "%n = OpVariable %_ptr_int Function\n" +
3110 "%load_n = OpLoad %int %n\n" +
3111 "%2 = OpSDiv %int %load_n %int_3\n" +
3112 "OpReturn\n" +
3113 "OpFunctionEnd",
3114 2, 0),
3115 // Test case 23: Don't fold n remainder 3
3116 InstructionFoldingCase<uint32_t>(
3117 Header() + "%main = OpFunction %void None %void_func\n" +
3118 "%main_lab = OpLabel\n" +
3119 "%n = OpVariable %_ptr_int Function\n" +
3120 "%load_n = OpLoad %int %n\n" +
3121 "%2 = OpSRem %int %load_n %int_3\n" +
3122 "OpReturn\n" +
3123 "OpFunctionEnd",
3124 2, 0),
3125 // Test case 24: Don't fold n % 3 (signed)
3126 InstructionFoldingCase<uint32_t>(
3127 Header() + "%main = OpFunction %void None %void_func\n" +
3128 "%main_lab = OpLabel\n" +
3129 "%n = OpVariable %_ptr_int Function\n" +
3130 "%load_n = OpLoad %int %n\n" +
3131 "%2 = OpSMod %int %load_n %int_3\n" +
3132 "OpReturn\n" +
3133 "OpFunctionEnd",
3134 2, 0),
3135 // Test case 25: Don't fold n % 3 (unsigned)
3136 InstructionFoldingCase<uint32_t>(
3137 Header() + "%main = OpFunction %void None %void_func\n" +
3138 "%main_lab = OpLabel\n" +
3139 "%n = OpVariable %_ptr_uint Function\n" +
3140 "%load_n = OpLoad %uint %n\n" +
3141 "%2 = OpUMod %int %load_n %int_3\n" +
3142 "OpReturn\n" +
3143 "OpFunctionEnd",
3144 2, 0),
3145 // Test case 26: Don't fold n << 3
3146 InstructionFoldingCase<uint32_t>(
3147 Header() + "%main = OpFunction %void None %void_func\n" +
3148 "%main_lab = OpLabel\n" +
3149 "%n = OpVariable %_ptr_uint Function\n" +
3150 "%load_n = OpLoad %uint %n\n" +
3151 "%2 = OpShiftRightLogical %int %load_n %int_3\n" +
3152 "OpReturn\n" +
3153 "OpFunctionEnd",
3154 2, 0),
3155 // Test case 27: Don't fold n >> 3
3156 InstructionFoldingCase<uint32_t>(
3157 Header() + "%main = OpFunction %void None %void_func\n" +
3158 "%main_lab = OpLabel\n" +
3159 "%n = OpVariable %_ptr_uint Function\n" +
3160 "%load_n = OpLoad %uint %n\n" +
3161 "%2 = OpShiftLeftLogical %int %load_n %int_3\n" +
3162 "OpReturn\n" +
3163 "OpFunctionEnd",
3164 2, 0),
3165 // Test case 28: Don't fold n | 3
3166 InstructionFoldingCase<uint32_t>(
3167 Header() + "%main = OpFunction %void None %void_func\n" +
3168 "%main_lab = OpLabel\n" +
3169 "%n = OpVariable %_ptr_uint Function\n" +
3170 "%load_n = OpLoad %uint %n\n" +
3171 "%2 = OpBitwiseOr %int %load_n %int_3\n" +
3172 "OpReturn\n" +
3173 "OpFunctionEnd",
3174 2, 0),
3175 // Test case 29: Don't fold n & 3
3176 InstructionFoldingCase<uint32_t>(
3177 Header() + "%main = OpFunction %void None %void_func\n" +
3178 "%main_lab = OpLabel\n" +
3179 "%n = OpVariable %_ptr_uint Function\n" +
3180 "%load_n = OpLoad %uint %n\n" +
3181 "%2 = OpBitwiseAnd %uint %load_n %uint_3\n" +
3182 "OpReturn\n" +
3183 "OpFunctionEnd",
3184 2, 0),
3185 // Test case 30: Don't fold n < 3 (unsigned)
3186 InstructionFoldingCase<uint32_t>(
3187 Header() + "%main = OpFunction %void None %void_func\n" +
3188 "%main_lab = OpLabel\n" +
3189 "%n = OpVariable %_ptr_uint Function\n" +
3190 "%load_n = OpLoad %uint %n\n" +
3191 "%2 = OpULessThan %bool %load_n %uint_3\n" +
3192 "OpReturn\n" +
3193 "OpFunctionEnd",
3194 2, 0),
3195 // Test case 31: Don't fold n > 3 (unsigned)
3196 InstructionFoldingCase<uint32_t>(
3197 Header() + "%main = OpFunction %void None %void_func\n" +
3198 "%main_lab = OpLabel\n" +
3199 "%n = OpVariable %_ptr_uint Function\n" +
3200 "%load_n = OpLoad %uint %n\n" +
3201 "%2 = OpUGreaterThan %bool %load_n %uint_3\n" +
3202 "OpReturn\n" +
3203 "OpFunctionEnd",
3204 2, 0),
3205 // Test case 32: Don't fold n <= 3 (unsigned)
3206 InstructionFoldingCase<uint32_t>(
3207 Header() + "%main = OpFunction %void None %void_func\n" +
3208 "%main_lab = OpLabel\n" +
3209 "%n = OpVariable %_ptr_uint Function\n" +
3210 "%load_n = OpLoad %uint %n\n" +
3211 "%2 = OpULessThanEqual %bool %load_n %uint_3\n" +
3212 "OpReturn\n" +
3213 "OpFunctionEnd",
3214 2, 0),
3215 // Test case 33: Don't fold n >= 3 (unsigned)
3216 InstructionFoldingCase<uint32_t>(
3217 Header() + "%main = OpFunction %void None %void_func\n" +
3218 "%main_lab = OpLabel\n" +
3219 "%n = OpVariable %_ptr_uint Function\n" +
3220 "%load_n = OpLoad %uint %n\n" +
3221 "%2 = OpUGreaterThanEqual %bool %load_n %uint_3\n" +
3222 "OpReturn\n" +
3223 "OpFunctionEnd",
3224 2, 0),
3225 // Test case 34: Don't fold n < 3 (signed)
3226 InstructionFoldingCase<uint32_t>(
3227 Header() + "%main = OpFunction %void None %void_func\n" +
3228 "%main_lab = OpLabel\n" +
3229 "%n = OpVariable %_ptr_int Function\n" +
3230 "%load_n = OpLoad %int %n\n" +
3231 "%2 = OpULessThan %bool %load_n %int_3\n" +
3232 "OpReturn\n" +
3233 "OpFunctionEnd",
3234 2, 0),
3235 // Test case 35: Don't fold n > 3 (signed)
3236 InstructionFoldingCase<uint32_t>(
3237 Header() + "%main = OpFunction %void None %void_func\n" +
3238 "%main_lab = OpLabel\n" +
3239 "%n = OpVariable %_ptr_int Function\n" +
3240 "%load_n = OpLoad %int %n\n" +
3241 "%2 = OpUGreaterThan %bool %load_n %int_3\n" +
3242 "OpReturn\n" +
3243 "OpFunctionEnd",
3244 2, 0),
3245 // Test case 36: Don't fold n <= 3 (signed)
3246 InstructionFoldingCase<uint32_t>(
3247 Header() + "%main = OpFunction %void None %void_func\n" +
3248 "%main_lab = OpLabel\n" +
3249 "%n = OpVariable %_ptr_int Function\n" +
3250 "%load_n = OpLoad %int %n\n" +
3251 "%2 = OpULessThanEqual %bool %load_n %int_3\n" +
3252 "OpReturn\n" +
3253 "OpFunctionEnd",
3254 2, 0),
3255 // Test case 37: Don't fold n >= 3 (signed)
3256 InstructionFoldingCase<uint32_t>(
3257 Header() + "%main = OpFunction %void None %void_func\n" +
3258 "%main_lab = OpLabel\n" +
3259 "%n = OpVariable %_ptr_int Function\n" +
3260 "%load_n = OpLoad %int %n\n" +
3261 "%2 = OpUGreaterThanEqual %bool %load_n %int_3\n" +
3262 "OpReturn\n" +
3263 "OpFunctionEnd",
3264 2, 0),
3265 // Test case 38: Don't fold 2 + 3 (long), bad length
3266 InstructionFoldingCase<uint32_t>(
3267 Header() + "%main = OpFunction %void None %void_func\n" +
3268 "%main_lab = OpLabel\n" +
3269 "%2 = OpIAdd %long %long_2 %long_3\n" +
3270 "OpReturn\n" +
3271 "OpFunctionEnd",
3272 2, 0),
3273 // Test case 39: Don't fold 2 + 3 (short), bad length
3274 InstructionFoldingCase<uint32_t>(
3275 Header() + "%main = OpFunction %void None %void_func\n" +
3276 "%main_lab = OpLabel\n" +
3277 "%2 = OpIAdd %short %short_2 %short_3\n" +
3278 "OpReturn\n" +
3279 "OpFunctionEnd",
3280 2, 0),
3281 // Test case 40: fold 1*n
3282 InstructionFoldingCase<uint32_t>(
3283 Header() + "%main = OpFunction %void None %void_func\n" +
3284 "%main_lab = OpLabel\n" +
3285 "%n = OpVariable %_ptr_int Function\n" +
3286 "%3 = OpLoad %int %n\n" +
3287 "%2 = OpIMul %int %int_1 %3\n" +
3288 "OpReturn\n" +
3289 "OpFunctionEnd",
3290 2, 3),
3291 // Test case 41: fold n*1
3292 InstructionFoldingCase<uint32_t>(
3293 Header() + "%main = OpFunction %void None %void_func\n" +
3294 "%main_lab = OpLabel\n" +
3295 "%n = OpVariable %_ptr_int Function\n" +
3296 "%3 = OpLoad %int %n\n" +
3297 "%2 = OpIMul %int %3 %int_1\n" +
3298 "OpReturn\n" +
3299 "OpFunctionEnd",
3300 2, 3),
3301 // Test case 42: Don't fold comparisons of 64-bit types
3302 // (https://github.com/KhronosGroup/SPIRV-Tools/issues/3343).
3303 InstructionFoldingCase<uint32_t>(
3304 Header() + "%main = OpFunction %void None %void_func\n" +
3305 "%main_lab = OpLabel\n" +
3306 "%2 = OpSLessThan %bool %long_0 %long_2\n" +
3307 "OpReturn\n" +
3308 "OpFunctionEnd",
3309 2, 0)
3310 ));
3311
3312 INSTANTIATE_TEST_SUITE_P(CompositeExtractFoldingTest, GeneralInstructionFoldingTest,
3313 ::testing::Values(
3314 // Test case 0: fold Insert feeding extract
3315 InstructionFoldingCase<uint32_t>(
3316 Header() + "%main = OpFunction %void None %void_func\n" +
3317 "%main_lab = OpLabel\n" +
3318 "%n = OpVariable %_ptr_int Function\n" +
3319 "%2 = OpLoad %int %n\n" +
3320 "%3 = OpCompositeInsert %v4int %2 %v4int_0_0_0_0 0\n" +
3321 "%4 = OpCompositeInsert %v4int %int_1 %3 1\n" +
3322 "%5 = OpCompositeInsert %v4int %int_1 %4 2\n" +
3323 "%6 = OpCompositeInsert %v4int %int_1 %5 3\n" +
3324 "%7 = OpCompositeExtract %int %6 0\n" +
3325 "OpReturn\n" +
3326 "OpFunctionEnd",
3327 7, 2),
3328 // Test case 1: fold Composite construct feeding extract (position 0)
3329 InstructionFoldingCase<uint32_t>(
3330 Header() + "%main = OpFunction %void None %void_func\n" +
3331 "%main_lab = OpLabel\n" +
3332 "%n = OpVariable %_ptr_int Function\n" +
3333 "%2 = OpLoad %int %n\n" +
3334 "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %int_0\n" +
3335 "%4 = OpCompositeExtract %int %3 0\n" +
3336 "OpReturn\n" +
3337 "OpFunctionEnd",
3338 4, 2),
3339 // Test case 2: fold Composite construct feeding extract (position 3)
3340 InstructionFoldingCase<uint32_t>(
3341 Header() + "%main = OpFunction %void None %void_func\n" +
3342 "%main_lab = OpLabel\n" +
3343 "%n = OpVariable %_ptr_int Function\n" +
3344 "%2 = OpLoad %int %n\n" +
3345 "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %100\n" +
3346 "%4 = OpCompositeExtract %int %3 3\n" +
3347 "OpReturn\n" +
3348 "OpFunctionEnd",
3349 4, INT_0_ID),
3350 // Test case 3: fold Composite construct with vectors feeding extract (scalar element)
3351 InstructionFoldingCase<uint32_t>(
3352 Header() + "%main = OpFunction %void None %void_func\n" +
3353 "%main_lab = OpLabel\n" +
3354 "%n = OpVariable %_ptr_int Function\n" +
3355 "%2 = OpLoad %int %n\n" +
3356 "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
3357 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
3358 "%5 = OpCompositeExtract %int %4 3\n" +
3359 "OpReturn\n" +
3360 "OpFunctionEnd",
3361 5, INT_0_ID),
3362 // Test case 4: fold Composite construct with vectors feeding extract (start of vector element)
3363 InstructionFoldingCase<uint32_t>(
3364 Header() + "%main = OpFunction %void None %void_func\n" +
3365 "%main_lab = OpLabel\n" +
3366 "%n = OpVariable %_ptr_int Function\n" +
3367 "%2 = OpLoad %int %n\n" +
3368 "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
3369 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
3370 "%5 = OpCompositeExtract %int %4 0\n" +
3371 "OpReturn\n" +
3372 "OpFunctionEnd",
3373 5, 2),
3374 // Test case 5: fold Composite construct with vectors feeding extract (middle of vector element)
3375 InstructionFoldingCase<uint32_t>(
3376 Header() + "%main = OpFunction %void None %void_func\n" +
3377 "%main_lab = OpLabel\n" +
3378 "%n = OpVariable %_ptr_int Function\n" +
3379 "%2 = OpLoad %int %n\n" +
3380 "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
3381 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
3382 "%5 = OpCompositeExtract %int %4 1\n" +
3383 "OpReturn\n" +
3384 "OpFunctionEnd",
3385 5, 2),
3386 // Test case 6: fold Composite construct with multiple indices.
3387 InstructionFoldingCase<uint32_t>(
3388 Header() + "%main = OpFunction %void None %void_func\n" +
3389 "%main_lab = OpLabel\n" +
3390 "%n = OpVariable %_ptr_int Function\n" +
3391 "%2 = OpLoad %int %n\n" +
3392 "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
3393 "%4 = OpCompositeConstruct %struct_v2int_int_int %3 %int_0 %100\n" +
3394 "%5 = OpCompositeExtract %int %4 0 1\n" +
3395 "OpReturn\n" +
3396 "OpFunctionEnd",
3397 5, 2),
3398 // Test case 7: fold constant extract.
3399 InstructionFoldingCase<uint32_t>(
3400 Header() + "%main = OpFunction %void None %void_func\n" +
3401 "%main_lab = OpLabel\n" +
3402 "%2 = OpCompositeExtract %int %102 1\n" +
3403 "OpReturn\n" +
3404 "OpFunctionEnd",
3405 2, INT_7_ID),
3406 // Test case 8: constant struct has OpUndef
3407 InstructionFoldingCase<uint32_t>(
3408 Header() + "%main = OpFunction %void None %void_func\n" +
3409 "%main_lab = OpLabel\n" +
3410 "%2 = OpCompositeExtract %int %struct_undef_0_0 0 1\n" +
3411 "OpReturn\n" +
3412 "OpFunctionEnd",
3413 2, 0),
3414 // Test case 9: Extracting a member of element inserted via Insert
3415 InstructionFoldingCase<uint32_t>(
3416 Header() + "%main = OpFunction %void None %void_func\n" +
3417 "%main_lab = OpLabel\n" +
3418 "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
3419 "%2 = OpLoad %struct_v2int_int_int %n\n" +
3420 "%3 = OpCompositeInsert %struct_v2int_int_int %102 %2 0\n" +
3421 "%4 = OpCompositeExtract %int %3 0 1\n" +
3422 "OpReturn\n" +
3423 "OpFunctionEnd",
3424 4, 103),
3425 // Test case 10: Extracting a element that is partially changed by Insert. (Don't fold)
3426 InstructionFoldingCase<uint32_t>(
3427 Header() + "%main = OpFunction %void None %void_func\n" +
3428 "%main_lab = OpLabel\n" +
3429 "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
3430 "%2 = OpLoad %struct_v2int_int_int %n\n" +
3431 "%3 = OpCompositeInsert %struct_v2int_int_int %int_0 %2 0 1\n" +
3432 "%4 = OpCompositeExtract %v2int %3 0\n" +
3433 "OpReturn\n" +
3434 "OpFunctionEnd",
3435 4, 0),
3436 // Test case 11: Extracting from result of vector shuffle (first input)
3437 InstructionFoldingCase<uint32_t>(
3438 Header() + "%main = OpFunction %void None %void_func\n" +
3439 "%main_lab = OpLabel\n" +
3440 "%n = OpVariable %_ptr_v2int Function\n" +
3441 "%2 = OpLoad %v2int %n\n" +
3442 "%3 = OpVectorShuffle %v2int %102 %2 3 0\n" +
3443 "%4 = OpCompositeExtract %int %3 1\n" +
3444 "OpReturn\n" +
3445 "OpFunctionEnd",
3446 4, INT_7_ID),
3447 // Test case 12: Extracting from result of vector shuffle (second input)
3448 InstructionFoldingCase<uint32_t>(
3449 Header() + "%main = OpFunction %void None %void_func\n" +
3450 "%main_lab = OpLabel\n" +
3451 "%n = OpVariable %_ptr_v2int Function\n" +
3452 "%2 = OpLoad %v2int %n\n" +
3453 "%3 = OpVectorShuffle %v2int %2 %102 2 0\n" +
3454 "%4 = OpCompositeExtract %int %3 0\n" +
3455 "OpReturn\n" +
3456 "OpFunctionEnd",
3457 4, INT_7_ID),
3458 // Test case 13: https://github.com/KhronosGroup/SPIRV-Tools/issues/2608
3459 // Out of bounds access. Do not fold.
3460 InstructionFoldingCase<uint32_t>(
3461 Header() + "%main = OpFunction %void None %void_func\n" +
3462 "%main_lab = OpLabel\n" +
3463 "%2 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n" +
3464 "%3 = OpCompositeExtract %float %2 4\n" +
3465 "OpReturn\n" +
3466 "OpFunctionEnd",
3467 3, 0),
3468 // Test case 14: https://github.com/KhronosGroup/SPIRV-Tools/issues/3631
3469 // Extract the component right after the vector constituent.
3470 InstructionFoldingCase<uint32_t>(
3471 Header() + "%main = OpFunction %void None %void_func\n" +
3472 "%main_lab = OpLabel\n" +
3473 "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
3474 "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
3475 "%4 = OpCompositeExtract %int %3 2\n" +
3476 "OpReturn\n" +
3477 "OpFunctionEnd",
3478 4, INT_0_ID)
3479 ));
3480
3481 INSTANTIATE_TEST_SUITE_P(CompositeConstructFoldingTest, GeneralInstructionFoldingTest,
3482 ::testing::Values(
3483 // Test case 0: fold Extracts feeding construct
3484 InstructionFoldingCase<uint32_t>(
3485 Header() + "%main = OpFunction %void None %void_func\n" +
3486 "%main_lab = OpLabel\n" +
3487 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
3488 "%3 = OpCompositeExtract %int %2 0\n" +
3489 "%4 = OpCompositeExtract %int %2 1\n" +
3490 "%5 = OpCompositeExtract %int %2 2\n" +
3491 "%6 = OpCompositeExtract %int %2 3\n" +
3492 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
3493 "OpReturn\n" +
3494 "OpFunctionEnd",
3495 7, 2),
3496 // Test case 1: Don't fold Extracts feeding construct (Different source)
3497 InstructionFoldingCase<uint32_t>(
3498 Header() + "%main = OpFunction %void None %void_func\n" +
3499 "%main_lab = OpLabel\n" +
3500 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
3501 "%3 = OpCompositeExtract %int %2 0\n" +
3502 "%4 = OpCompositeExtract %int %2 1\n" +
3503 "%5 = OpCompositeExtract %int %2 2\n" +
3504 "%6 = OpCompositeExtract %int %v4int_0_0_0_0 3\n" +
3505 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
3506 "OpReturn\n" +
3507 "OpFunctionEnd",
3508 7, 0),
3509 // Test case 2: Don't fold Extracts feeding construct (bad indices)
3510 InstructionFoldingCase<uint32_t>(
3511 Header() + "%main = OpFunction %void None %void_func\n" +
3512 "%main_lab = OpLabel\n" +
3513 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
3514 "%3 = OpCompositeExtract %int %2 0\n" +
3515 "%4 = OpCompositeExtract %int %2 0\n" +
3516 "%5 = OpCompositeExtract %int %2 2\n" +
3517 "%6 = OpCompositeExtract %int %2 3\n" +
3518 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
3519 "OpReturn\n" +
3520 "OpFunctionEnd",
3521 7, 0),
3522 // Test case 3: Don't fold Extracts feeding construct (different type)
3523 InstructionFoldingCase<uint32_t>(
3524 Header() + "%main = OpFunction %void None %void_func\n" +
3525 "%main_lab = OpLabel\n" +
3526 "%2 = OpCopyObject %struct_v2int_int_int %struct_v2int_int_int_null\n" +
3527 "%3 = OpCompositeExtract %v2int %2 0\n" +
3528 "%4 = OpCompositeExtract %int %2 1\n" +
3529 "%5 = OpCompositeExtract %int %2 2\n" +
3530 "%7 = OpCompositeConstruct %v4int %3 %4 %5\n" +
3531 "OpReturn\n" +
3532 "OpFunctionEnd",
3533 7, 0),
3534 // Test case 4: Fold construct with constants to constant.
3535 InstructionFoldingCase<uint32_t>(
3536 Header() + "%main = OpFunction %void None %void_func\n" +
3537 "%main_lab = OpLabel\n" +
3538 "%2 = OpCompositeConstruct %v2int %103 %103\n" +
3539 "OpReturn\n" +
3540 "OpFunctionEnd",
3541 2, VEC2_0_ID),
3542 // Test case 5: Don't segfault when trying to fold an OpCompositeConstruct
3543 // for an empty struct, and we reached the id limit.
3544 InstructionFoldingCase<uint32_t>(
3545 Header() + "%empty_struct = OpTypeStruct\n" +
3546 "%main = OpFunction %void None %void_func\n" +
3547 "%main_lab = OpLabel\n" +
3548 "%4194303 = OpCompositeConstruct %empty_struct\n" +
3549 "OpReturn\n" +
3550 "OpFunctionEnd",
3551 4194303, 0)
3552 ));
3553
3554 INSTANTIATE_TEST_SUITE_P(PhiFoldingTest, GeneralInstructionFoldingTest,
3555 ::testing::Values(
3556 // Test case 0: Fold phi with the same values for all edges.
3557 InstructionFoldingCase<uint32_t>(
3558 Header() + "%main = OpFunction %void None %void_func\n" +
3559 "%main_lab = OpLabel\n" +
3560 " OpBranchConditional %true %l1 %l2\n" +
3561 "%l1 = OpLabel\n" +
3562 " OpBranch %merge_lab\n" +
3563 "%l2 = OpLabel\n" +
3564 " OpBranch %merge_lab\n" +
3565 "%merge_lab = OpLabel\n" +
3566 "%2 = OpPhi %int %100 %l1 %100 %l2\n" +
3567 "OpReturn\n" +
3568 "OpFunctionEnd",
3569 2, INT_0_ID),
3570 // Test case 1: Fold phi in pass through loop.
3571 InstructionFoldingCase<uint32_t>(
3572 Header() + "%main = OpFunction %void None %void_func\n" +
3573 "%main_lab = OpLabel\n" +
3574 " OpBranch %l1\n" +
3575 "%l1 = OpLabel\n" +
3576 "%2 = OpPhi %int %100 %main_lab %2 %l1\n" +
3577 " OpBranchConditional %true %l1 %merge_lab\n" +
3578 "%merge_lab = OpLabel\n" +
3579 "OpReturn\n" +
3580 "OpFunctionEnd",
3581 2, INT_0_ID),
3582 // Test case 2: Don't Fold phi because of different values.
3583 InstructionFoldingCase<uint32_t>(
3584 Header() + "%main = OpFunction %void None %void_func\n" +
3585 "%main_lab = OpLabel\n" +
3586 " OpBranch %l1\n" +
3587 "%l1 = OpLabel\n" +
3588 "%2 = OpPhi %int %int_0 %main_lab %int_3 %l1\n" +
3589 " OpBranchConditional %true %l1 %merge_lab\n" +
3590 "%merge_lab = OpLabel\n" +
3591 "OpReturn\n" +
3592 "OpFunctionEnd",
3593 2, 0)
3594 ));
3595
3596 INSTANTIATE_TEST_SUITE_P(FloatRedundantFoldingTest, GeneralInstructionFoldingTest,
3597 ::testing::Values(
3598 // Test case 0: Don't fold n + 1.0
3599 InstructionFoldingCase<uint32_t>(
3600 Header() + "%main = OpFunction %void None %void_func\n" +
3601 "%main_lab = OpLabel\n" +
3602 "%n = OpVariable %_ptr_float Function\n" +
3603 "%3 = OpLoad %float %n\n" +
3604 "%2 = OpFAdd %float %3 %float_2\n" +
3605 "OpReturn\n" +
3606 "OpFunctionEnd",
3607 2, 0),
3608 // Test case 1: Don't fold n - 1.0
3609 InstructionFoldingCase<uint32_t>(
3610 Header() + "%main = OpFunction %void None %void_func\n" +
3611 "%main_lab = OpLabel\n" +
3612 "%n = OpVariable %_ptr_float Function\n" +
3613 "%3 = OpLoad %float %n\n" +
3614 "%2 = OpFSub %float %3 %float_2\n" +
3615 "OpReturn\n" +
3616 "OpFunctionEnd",
3617 2, 0),
3618 // Test case 2: Don't fold n * 2.0
3619 InstructionFoldingCase<uint32_t>(
3620 Header() + "%main = OpFunction %void None %void_func\n" +
3621 "%main_lab = OpLabel\n" +
3622 "%n = OpVariable %_ptr_float Function\n" +
3623 "%3 = OpLoad %float %n\n" +
3624 "%2 = OpFMul %float %3 %float_2\n" +
3625 "OpReturn\n" +
3626 "OpFunctionEnd",
3627 2, 0),
3628 // Test case 3: Fold n + 0.0
3629 InstructionFoldingCase<uint32_t>(
3630 Header() + "%main = OpFunction %void None %void_func\n" +
3631 "%main_lab = OpLabel\n" +
3632 "%n = OpVariable %_ptr_float Function\n" +
3633 "%3 = OpLoad %float %n\n" +
3634 "%2 = OpFAdd %float %3 %float_0\n" +
3635 "OpReturn\n" +
3636 "OpFunctionEnd",
3637 2, 3),
3638 // Test case 4: Fold 0.0 + n
3639 InstructionFoldingCase<uint32_t>(
3640 Header() + "%main = OpFunction %void None %void_func\n" +
3641 "%main_lab = OpLabel\n" +
3642 "%n = OpVariable %_ptr_float Function\n" +
3643 "%3 = OpLoad %float %n\n" +
3644 "%2 = OpFAdd %float %float_0 %3\n" +
3645 "OpReturn\n" +
3646 "OpFunctionEnd",
3647 2, 3),
3648 // Test case 5: Fold n - 0.0
3649 InstructionFoldingCase<uint32_t>(
3650 Header() + "%main = OpFunction %void None %void_func\n" +
3651 "%main_lab = OpLabel\n" +
3652 "%n = OpVariable %_ptr_float Function\n" +
3653 "%3 = OpLoad %float %n\n" +
3654 "%2 = OpFSub %float %3 %float_0\n" +
3655 "OpReturn\n" +
3656 "OpFunctionEnd",
3657 2, 3),
3658 // Test case 6: Fold n * 1.0
3659 InstructionFoldingCase<uint32_t>(
3660 Header() + "%main = OpFunction %void None %void_func\n" +
3661 "%main_lab = OpLabel\n" +
3662 "%n = OpVariable %_ptr_float Function\n" +
3663 "%3 = OpLoad %float %n\n" +
3664 "%2 = OpFMul %float %3 %float_1\n" +
3665 "OpReturn\n" +
3666 "OpFunctionEnd",
3667 2, 3),
3668 // Test case 7: Fold 1.0 * n
3669 InstructionFoldingCase<uint32_t>(
3670 Header() + "%main = OpFunction %void None %void_func\n" +
3671 "%main_lab = OpLabel\n" +
3672 "%n = OpVariable %_ptr_float Function\n" +
3673 "%3 = OpLoad %float %n\n" +
3674 "%2 = OpFMul %float %float_1 %3\n" +
3675 "OpReturn\n" +
3676 "OpFunctionEnd",
3677 2, 3),
3678 // Test case 8: Fold n / 1.0
3679 InstructionFoldingCase<uint32_t>(
3680 Header() + "%main = OpFunction %void None %void_func\n" +
3681 "%main_lab = OpLabel\n" +
3682 "%n = OpVariable %_ptr_float Function\n" +
3683 "%3 = OpLoad %float %n\n" +
3684 "%2 = OpFDiv %float %3 %float_1\n" +
3685 "OpReturn\n" +
3686 "OpFunctionEnd",
3687 2, 3),
3688 // Test case 9: Fold n * 0.0
3689 InstructionFoldingCase<uint32_t>(
3690 Header() + "%main = OpFunction %void None %void_func\n" +
3691 "%main_lab = OpLabel\n" +
3692 "%n = OpVariable %_ptr_float Function\n" +
3693 "%3 = OpLoad %float %n\n" +
3694 "%2 = OpFMul %float %3 %104\n" +
3695 "OpReturn\n" +
3696 "OpFunctionEnd",
3697 2, FLOAT_0_ID),
3698 // Test case 10: Fold 0.0 * n
3699 InstructionFoldingCase<uint32_t>(
3700 Header() + "%main = OpFunction %void None %void_func\n" +
3701 "%main_lab = OpLabel\n" +
3702 "%n = OpVariable %_ptr_float Function\n" +
3703 "%3 = OpLoad %float %n\n" +
3704 "%2 = OpFMul %float %104 %3\n" +
3705 "OpReturn\n" +
3706 "OpFunctionEnd",
3707 2, FLOAT_0_ID),
3708 // Test case 11: Fold 0.0 / n
3709 InstructionFoldingCase<uint32_t>(
3710 Header() + "%main = OpFunction %void None %void_func\n" +
3711 "%main_lab = OpLabel\n" +
3712 "%n = OpVariable %_ptr_float Function\n" +
3713 "%3 = OpLoad %float %n\n" +
3714 "%2 = OpFDiv %float %104 %3\n" +
3715 "OpReturn\n" +
3716 "OpFunctionEnd",
3717 2, FLOAT_0_ID),
3718 // Test case 12: Don't fold mix(a, b, 2.0)
3719 InstructionFoldingCase<uint32_t>(
3720 Header() + "%main = OpFunction %void None %void_func\n" +
3721 "%main_lab = OpLabel\n" +
3722 "%a = OpVariable %_ptr_float Function\n" +
3723 "%b = OpVariable %_ptr_float Function\n" +
3724 "%3 = OpLoad %float %a\n" +
3725 "%4 = OpLoad %float %b\n" +
3726 "%2 = OpExtInst %float %1 FMix %3 %4 %float_2\n" +
3727 "OpReturn\n" +
3728 "OpFunctionEnd",
3729 2, 0),
3730 // Test case 13: Fold mix(a, b, 0.0)
3731 InstructionFoldingCase<uint32_t>(
3732 Header() + "%main = OpFunction %void None %void_func\n" +
3733 "%main_lab = OpLabel\n" +
3734 "%a = OpVariable %_ptr_float Function\n" +
3735 "%b = OpVariable %_ptr_float Function\n" +
3736 "%3 = OpLoad %float %a\n" +
3737 "%4 = OpLoad %float %b\n" +
3738 "%2 = OpExtInst %float %1 FMix %3 %4 %float_0\n" +
3739 "OpReturn\n" +
3740 "OpFunctionEnd",
3741 2, 3),
3742 // Test case 14: Fold mix(a, b, 1.0)
3743 InstructionFoldingCase<uint32_t>(
3744 Header() + "%main = OpFunction %void None %void_func\n" +
3745 "%main_lab = OpLabel\n" +
3746 "%a = OpVariable %_ptr_float Function\n" +
3747 "%b = OpVariable %_ptr_float Function\n" +
3748 "%3 = OpLoad %float %a\n" +
3749 "%4 = OpLoad %float %b\n" +
3750 "%2 = OpExtInst %float %1 FMix %3 %4 %float_1\n" +
3751 "OpReturn\n" +
3752 "OpFunctionEnd",
3753 2, 4),
3754 // Test case 15: Fold vector fadd with null
3755 InstructionFoldingCase<uint32_t>(
3756 Header() + "%main = OpFunction %void None %void_func\n" +
3757 "%main_lab = OpLabel\n" +
3758 "%a = OpVariable %_ptr_v2float Function\n" +
3759 "%2 = OpLoad %v2float %a\n" +
3760 "%3 = OpFAdd %v2float %2 %v2float_null\n" +
3761 "OpReturn\n" +
3762 "OpFunctionEnd",
3763 3, 2),
3764 // Test case 16: Fold vector fadd with null
3765 InstructionFoldingCase<uint32_t>(
3766 Header() + "%main = OpFunction %void None %void_func\n" +
3767 "%main_lab = OpLabel\n" +
3768 "%a = OpVariable %_ptr_v2float Function\n" +
3769 "%2 = OpLoad %v2float %a\n" +
3770 "%3 = OpFAdd %v2float %v2float_null %2\n" +
3771 "OpReturn\n" +
3772 "OpFunctionEnd",
3773 3, 2),
3774 // Test case 17: Fold vector fsub with null
3775 InstructionFoldingCase<uint32_t>(
3776 Header() + "%main = OpFunction %void None %void_func\n" +
3777 "%main_lab = OpLabel\n" +
3778 "%a = OpVariable %_ptr_v2float Function\n" +
3779 "%2 = OpLoad %v2float %a\n" +
3780 "%3 = OpFSub %v2float %2 %v2float_null\n" +
3781 "OpReturn\n" +
3782 "OpFunctionEnd",
3783 3, 2),
3784 // Test case 18: Fold 0.0(half) * n
3785 InstructionFoldingCase<uint32_t>(
3786 Header() + "%main = OpFunction %void None %void_func\n" +
3787 "%main_lab = OpLabel\n" +
3788 "%n = OpVariable %_ptr_half Function\n" +
3789 "%3 = OpLoad %half %n\n" +
3790 "%2 = OpFMul %half %108 %3\n" +
3791 "OpReturn\n" +
3792 "OpFunctionEnd",
3793 2, HALF_0_ID),
3794 // Test case 19: Don't fold 1.0(half) * n
3795 InstructionFoldingCase<uint32_t>(
3796 Header() + "%main = OpFunction %void None %void_func\n" +
3797 "%main_lab = OpLabel\n" +
3798 "%n = OpVariable %_ptr_half Function\n" +
3799 "%3 = OpLoad %half %n\n" +
3800 "%2 = OpFMul %half %half_1 %3\n" +
3801 "OpReturn\n" +
3802 "OpFunctionEnd",
3803 2, 0),
3804 // Test case 20: Don't fold 1.0 * 1.0 (half)
3805 InstructionFoldingCase<uint32_t>(
3806 Header() + "%main = OpFunction %void None %void_func\n" +
3807 "%main_lab = OpLabel\n" +
3808 "%2 = OpFMul %half %half_1 %half_1\n" +
3809 "OpReturn\n" +
3810 "OpFunctionEnd",
3811 2, 0),
3812 // Test case 21: Don't fold (0.0, 1.0) * (0.0, 1.0) (half)
3813 InstructionFoldingCase<uint32_t>(
3814 Header() + "%main = OpFunction %void None %void_func\n" +
3815 "%main_lab = OpLabel\n" +
3816 "%2 = OpFMul %v2half %half_0_1 %half_0_1\n" +
3817 "OpReturn\n" +
3818 "OpFunctionEnd",
3819 2, 0),
3820 // Test case 22: Don't fold (0.0, 1.0) dotp (0.0, 1.0) (half)
3821 InstructionFoldingCase<uint32_t>(
3822 Header() + "%main = OpFunction %void None %void_func\n" +
3823 "%main_lab = OpLabel\n" +
3824 "%2 = OpDot %half %half_0_1 %half_0_1\n" +
3825 "OpReturn\n" +
3826 "OpFunctionEnd",
3827 2, 0)
3828 ));
3829
3830 INSTANTIATE_TEST_SUITE_P(DoubleRedundantFoldingTest, GeneralInstructionFoldingTest,
3831 ::testing::Values(
3832 // Test case 0: Don't fold n + 1.0
3833 InstructionFoldingCase<uint32_t>(
3834 Header() + "%main = OpFunction %void None %void_func\n" +
3835 "%main_lab = OpLabel\n" +
3836 "%n = OpVariable %_ptr_double Function\n" +
3837 "%3 = OpLoad %double %n\n" +
3838 "%2 = OpFAdd %double %3 %double_2\n" +
3839 "OpReturn\n" +
3840 "OpFunctionEnd",
3841 2, 0),
3842 // Test case 1: Don't fold n - 1.0
3843 InstructionFoldingCase<uint32_t>(
3844 Header() + "%main = OpFunction %void None %void_func\n" +
3845 "%main_lab = OpLabel\n" +
3846 "%n = OpVariable %_ptr_double Function\n" +
3847 "%3 = OpLoad %double %n\n" +
3848 "%2 = OpFSub %double %3 %double_2\n" +
3849 "OpReturn\n" +
3850 "OpFunctionEnd",
3851 2, 0),
3852 // Test case 2: Don't fold n * 2.0
3853 InstructionFoldingCase<uint32_t>(
3854 Header() + "%main = OpFunction %void None %void_func\n" +
3855 "%main_lab = OpLabel\n" +
3856 "%n = OpVariable %_ptr_double Function\n" +
3857 "%3 = OpLoad %double %n\n" +
3858 "%2 = OpFMul %double %3 %double_2\n" +
3859 "OpReturn\n" +
3860 "OpFunctionEnd",
3861 2, 0),
3862 // Test case 3: Fold n + 0.0
3863 InstructionFoldingCase<uint32_t>(
3864 Header() + "%main = OpFunction %void None %void_func\n" +
3865 "%main_lab = OpLabel\n" +
3866 "%n = OpVariable %_ptr_double Function\n" +
3867 "%3 = OpLoad %double %n\n" +
3868 "%2 = OpFAdd %double %3 %double_0\n" +
3869 "OpReturn\n" +
3870 "OpFunctionEnd",
3871 2, 3),
3872 // Test case 4: Fold 0.0 + n
3873 InstructionFoldingCase<uint32_t>(
3874 Header() + "%main = OpFunction %void None %void_func\n" +
3875 "%main_lab = OpLabel\n" +
3876 "%n = OpVariable %_ptr_double Function\n" +
3877 "%3 = OpLoad %double %n\n" +
3878 "%2 = OpFAdd %double %double_0 %3\n" +
3879 "OpReturn\n" +
3880 "OpFunctionEnd",
3881 2, 3),
3882 // Test case 5: Fold n - 0.0
3883 InstructionFoldingCase<uint32_t>(
3884 Header() + "%main = OpFunction %void None %void_func\n" +
3885 "%main_lab = OpLabel\n" +
3886 "%n = OpVariable %_ptr_double Function\n" +
3887 "%3 = OpLoad %double %n\n" +
3888 "%2 = OpFSub %double %3 %double_0\n" +
3889 "OpReturn\n" +
3890 "OpFunctionEnd",
3891 2, 3),
3892 // Test case 6: Fold n * 1.0
3893 InstructionFoldingCase<uint32_t>(
3894 Header() + "%main = OpFunction %void None %void_func\n" +
3895 "%main_lab = OpLabel\n" +
3896 "%n = OpVariable %_ptr_double Function\n" +
3897 "%3 = OpLoad %double %n\n" +
3898 "%2 = OpFMul %double %3 %double_1\n" +
3899 "OpReturn\n" +
3900 "OpFunctionEnd",
3901 2, 3),
3902 // Test case 7: Fold 1.0 * n
3903 InstructionFoldingCase<uint32_t>(
3904 Header() + "%main = OpFunction %void None %void_func\n" +
3905 "%main_lab = OpLabel\n" +
3906 "%n = OpVariable %_ptr_double Function\n" +
3907 "%3 = OpLoad %double %n\n" +
3908 "%2 = OpFMul %double %double_1 %3\n" +
3909 "OpReturn\n" +
3910 "OpFunctionEnd",
3911 2, 3),
3912 // Test case 8: Fold n / 1.0
3913 InstructionFoldingCase<uint32_t>(
3914 Header() + "%main = OpFunction %void None %void_func\n" +
3915 "%main_lab = OpLabel\n" +
3916 "%n = OpVariable %_ptr_double Function\n" +
3917 "%3 = OpLoad %double %n\n" +
3918 "%2 = OpFDiv %double %3 %double_1\n" +
3919 "OpReturn\n" +
3920 "OpFunctionEnd",
3921 2, 3),
3922 // Test case 9: Fold n * 0.0
3923 InstructionFoldingCase<uint32_t>(
3924 Header() + "%main = OpFunction %void None %void_func\n" +
3925 "%main_lab = OpLabel\n" +
3926 "%n = OpVariable %_ptr_double Function\n" +
3927 "%3 = OpLoad %double %n\n" +
3928 "%2 = OpFMul %double %3 %105\n" +
3929 "OpReturn\n" +
3930 "OpFunctionEnd",
3931 2, DOUBLE_0_ID),
3932 // Test case 10: Fold 0.0 * n
3933 InstructionFoldingCase<uint32_t>(
3934 Header() + "%main = OpFunction %void None %void_func\n" +
3935 "%main_lab = OpLabel\n" +
3936 "%n = OpVariable %_ptr_double Function\n" +
3937 "%3 = OpLoad %double %n\n" +
3938 "%2 = OpFMul %double %105 %3\n" +
3939 "OpReturn\n" +
3940 "OpFunctionEnd",
3941 2, DOUBLE_0_ID),
3942 // Test case 11: Fold 0.0 / n
3943 InstructionFoldingCase<uint32_t>(
3944 Header() + "%main = OpFunction %void None %void_func\n" +
3945 "%main_lab = OpLabel\n" +
3946 "%n = OpVariable %_ptr_double Function\n" +
3947 "%3 = OpLoad %double %n\n" +
3948 "%2 = OpFDiv %double %105 %3\n" +
3949 "OpReturn\n" +
3950 "OpFunctionEnd",
3951 2, DOUBLE_0_ID),
3952 // Test case 12: Don't fold mix(a, b, 2.0)
3953 InstructionFoldingCase<uint32_t>(
3954 Header() + "%main = OpFunction %void None %void_func\n" +
3955 "%main_lab = OpLabel\n" +
3956 "%a = OpVariable %_ptr_double Function\n" +
3957 "%b = OpVariable %_ptr_double Function\n" +
3958 "%3 = OpLoad %double %a\n" +
3959 "%4 = OpLoad %double %b\n" +
3960 "%2 = OpExtInst %double %1 FMix %3 %4 %double_2\n" +
3961 "OpReturn\n" +
3962 "OpFunctionEnd",
3963 2, 0),
3964 // Test case 13: Fold mix(a, b, 0.0)
3965 InstructionFoldingCase<uint32_t>(
3966 Header() + "%main = OpFunction %void None %void_func\n" +
3967 "%main_lab = OpLabel\n" +
3968 "%a = OpVariable %_ptr_double Function\n" +
3969 "%b = OpVariable %_ptr_double Function\n" +
3970 "%3 = OpLoad %double %a\n" +
3971 "%4 = OpLoad %double %b\n" +
3972 "%2 = OpExtInst %double %1 FMix %3 %4 %double_0\n" +
3973 "OpReturn\n" +
3974 "OpFunctionEnd",
3975 2, 3),
3976 // Test case 14: Fold mix(a, b, 1.0)
3977 InstructionFoldingCase<uint32_t>(
3978 Header() + "%main = OpFunction %void None %void_func\n" +
3979 "%main_lab = OpLabel\n" +
3980 "%a = OpVariable %_ptr_double Function\n" +
3981 "%b = OpVariable %_ptr_double Function\n" +
3982 "%3 = OpLoad %double %a\n" +
3983 "%4 = OpLoad %double %b\n" +
3984 "%2 = OpExtInst %double %1 FMix %3 %4 %double_1\n" +
3985 "OpReturn\n" +
3986 "OpFunctionEnd",
3987 2, 4)
3988 ));
3989
3990 INSTANTIATE_TEST_SUITE_P(FloatVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
3991 ::testing::Values(
3992 // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
3993 InstructionFoldingCase<uint32_t>(
3994 Header() + "%main = OpFunction %void None %void_func\n" +
3995 "%main_lab = OpLabel\n" +
3996 "%n = OpVariable %_ptr_v4float Function\n" +
3997 "%3 = OpLoad %v4float %n\n" +
3998 "%2 = OpFMul %v4float %3 %v4float_0_0_0_1\n" +
3999 "OpReturn\n" +
4000 "OpFunctionEnd",
4001 2, 0),
4002 // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
4003 InstructionFoldingCase<uint32_t>(
4004 Header() + "%main = OpFunction %void None %void_func\n" +
4005 "%main_lab = OpLabel\n" +
4006 "%n = OpVariable %_ptr_v4float Function\n" +
4007 "%3 = OpLoad %v4float %n\n" +
4008 "%2 = OpFMul %v4float %3 %106\n" +
4009 "OpReturn\n" +
4010 "OpFunctionEnd",
4011 2, VEC4_0_ID),
4012 // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
4013 InstructionFoldingCase<uint32_t>(
4014 Header() + "%main = OpFunction %void None %void_func\n" +
4015 "%main_lab = OpLabel\n" +
4016 "%n = OpVariable %_ptr_v4float Function\n" +
4017 "%3 = OpLoad %v4float %n\n" +
4018 "%2 = OpFMul %v4float %3 %v4float_1_1_1_1\n" +
4019 "OpReturn\n" +
4020 "OpFunctionEnd",
4021 2, 3)
4022 ));
4023
4024 INSTANTIATE_TEST_SUITE_P(DoubleVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
4025 ::testing::Values(
4026 // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
4027 InstructionFoldingCase<uint32_t>(
4028 Header() + "%main = OpFunction %void None %void_func\n" +
4029 "%main_lab = OpLabel\n" +
4030 "%n = OpVariable %_ptr_v4double Function\n" +
4031 "%3 = OpLoad %v4double %n\n" +
4032 "%2 = OpFMul %v4double %3 %v4double_0_0_0_1\n" +
4033 "OpReturn\n" +
4034 "OpFunctionEnd",
4035 2, 0),
4036 // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
4037 InstructionFoldingCase<uint32_t>(
4038 Header() + "%main = OpFunction %void None %void_func\n" +
4039 "%main_lab = OpLabel\n" +
4040 "%n = OpVariable %_ptr_v4double Function\n" +
4041 "%3 = OpLoad %v4double %n\n" +
4042 "%2 = OpFMul %v4double %3 %106\n" +
4043 "OpReturn\n" +
4044 "OpFunctionEnd",
4045 2, DVEC4_0_ID),
4046 // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
4047 InstructionFoldingCase<uint32_t>(
4048 Header() + "%main = OpFunction %void None %void_func\n" +
4049 "%main_lab = OpLabel\n" +
4050 "%n = OpVariable %_ptr_v4double Function\n" +
4051 "%3 = OpLoad %v4double %n\n" +
4052 "%2 = OpFMul %v4double %3 %v4double_1_1_1_1\n" +
4053 "OpReturn\n" +
4054 "OpFunctionEnd",
4055 2, 3)
4056 ));
4057
4058 INSTANTIATE_TEST_SUITE_P(IntegerRedundantFoldingTest, GeneralInstructionFoldingTest,
4059 ::testing::Values(
4060 // Test case 0: Don't fold n + 1
4061 InstructionFoldingCase<uint32_t>(
4062 Header() + "%main = OpFunction %void None %void_func\n" +
4063 "%main_lab = OpLabel\n" +
4064 "%n = OpVariable %_ptr_uint Function\n" +
4065 "%3 = OpLoad %uint %n\n" +
4066 "%2 = OpIAdd %uint %3 %uint_1\n" +
4067 "OpReturn\n" +
4068 "OpFunctionEnd",
4069 2, 0),
4070 // Test case 1: Don't fold 1 + n
4071 InstructionFoldingCase<uint32_t>(
4072 Header() + "%main = OpFunction %void None %void_func\n" +
4073 "%main_lab = OpLabel\n" +
4074 "%n = OpVariable %_ptr_uint Function\n" +
4075 "%3 = OpLoad %uint %n\n" +
4076 "%2 = OpIAdd %uint %uint_1 %3\n" +
4077 "OpReturn\n" +
4078 "OpFunctionEnd",
4079 2, 0),
4080 // Test case 2: Fold n + 0
4081 InstructionFoldingCase<uint32_t>(
4082 Header() + "%main = OpFunction %void None %void_func\n" +
4083 "%main_lab = OpLabel\n" +
4084 "%n = OpVariable %_ptr_uint Function\n" +
4085 "%3 = OpLoad %uint %n\n" +
4086 "%2 = OpIAdd %uint %3 %uint_0\n" +
4087 "OpReturn\n" +
4088 "OpFunctionEnd",
4089 2, 3),
4090 // Test case 3: Fold 0 + n
4091 InstructionFoldingCase<uint32_t>(
4092 Header() + "%main = OpFunction %void None %void_func\n" +
4093 "%main_lab = OpLabel\n" +
4094 "%n = OpVariable %_ptr_uint Function\n" +
4095 "%3 = OpLoad %uint %n\n" +
4096 "%2 = OpIAdd %uint %uint_0 %3\n" +
4097 "OpReturn\n" +
4098 "OpFunctionEnd",
4099 2, 3),
4100 // Test case 4: Don't fold n + (1,0)
4101 InstructionFoldingCase<uint32_t>(
4102 Header() + "%main = OpFunction %void None %void_func\n" +
4103 "%main_lab = OpLabel\n" +
4104 "%n = OpVariable %_ptr_v2int Function\n" +
4105 "%3 = OpLoad %v2int %n\n" +
4106 "%2 = OpIAdd %v2int %3 %v2int_1_0\n" +
4107 "OpReturn\n" +
4108 "OpFunctionEnd",
4109 2, 0),
4110 // Test case 5: Don't fold (1,0) + n
4111 InstructionFoldingCase<uint32_t>(
4112 Header() + "%main = OpFunction %void None %void_func\n" +
4113 "%main_lab = OpLabel\n" +
4114 "%n = OpVariable %_ptr_v2int Function\n" +
4115 "%3 = OpLoad %v2int %n\n" +
4116 "%2 = OpIAdd %v2int %v2int_1_0 %3\n" +
4117 "OpReturn\n" +
4118 "OpFunctionEnd",
4119 2, 0),
4120 // Test case 6: Fold n + (0,0)
4121 InstructionFoldingCase<uint32_t>(
4122 Header() + "%main = OpFunction %void None %void_func\n" +
4123 "%main_lab = OpLabel\n" +
4124 "%n = OpVariable %_ptr_v2int Function\n" +
4125 "%3 = OpLoad %v2int %n\n" +
4126 "%2 = OpIAdd %v2int %3 %v2int_0_0\n" +
4127 "OpReturn\n" +
4128 "OpFunctionEnd",
4129 2, 3),
4130 // Test case 7: Fold (0,0) + n
4131 InstructionFoldingCase<uint32_t>(
4132 Header() + "%main = OpFunction %void None %void_func\n" +
4133 "%main_lab = OpLabel\n" +
4134 "%n = OpVariable %_ptr_v2int Function\n" +
4135 "%3 = OpLoad %v2int %n\n" +
4136 "%2 = OpIAdd %v2int %v2int_0_0 %3\n" +
4137 "OpReturn\n" +
4138 "OpFunctionEnd",
4139 2, 3)
4140 ));
4141
4142 INSTANTIATE_TEST_SUITE_P(ClampAndCmpLHS, GeneralInstructionFoldingTest,
4143 ::testing::Values(
4144 // Test case 0: Don't Fold 0.0 < clamp(-1, 1)
4145 InstructionFoldingCase<uint32_t>(
4146 Header() + "%main = OpFunction %void None %void_func\n" +
4147 "%main_lab = OpLabel\n" +
4148 "%n = OpVariable %_ptr_float Function\n" +
4149 "%ld = OpLoad %float %n\n" +
4150 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4151 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
4152 "OpReturn\n" +
4153 "OpFunctionEnd",
4154 2, 0),
4155 // Test case 1: Don't Fold 0.0 < clamp(-1, 1)
4156 InstructionFoldingCase<uint32_t>(
4157 Header() + "%main = OpFunction %void None %void_func\n" +
4158 "%main_lab = OpLabel\n" +
4159 "%n = OpVariable %_ptr_float Function\n" +
4160 "%ld = OpLoad %float %n\n" +
4161 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4162 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
4163 "OpReturn\n" +
4164 "OpFunctionEnd",
4165 2, 0),
4166 // Test case 2: Don't Fold 0.0 <= clamp(-1, 1)
4167 InstructionFoldingCase<uint32_t>(
4168 Header() + "%main = OpFunction %void None %void_func\n" +
4169 "%main_lab = OpLabel\n" +
4170 "%n = OpVariable %_ptr_float Function\n" +
4171 "%ld = OpLoad %float %n\n" +
4172 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4173 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
4174 "OpReturn\n" +
4175 "OpFunctionEnd",
4176 2, 0),
4177 // Test case 3: Don't Fold 0.0 <= clamp(-1, 1)
4178 InstructionFoldingCase<uint32_t>(
4179 Header() + "%main = OpFunction %void None %void_func\n" +
4180 "%main_lab = OpLabel\n" +
4181 "%n = OpVariable %_ptr_float Function\n" +
4182 "%ld = OpLoad %float %n\n" +
4183 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4184 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
4185 "OpReturn\n" +
4186 "OpFunctionEnd",
4187 2, 0),
4188 // Test case 4: Don't Fold 0.0 > clamp(-1, 1)
4189 InstructionFoldingCase<uint32_t>(
4190 Header() + "%main = OpFunction %void None %void_func\n" +
4191 "%main_lab = OpLabel\n" +
4192 "%n = OpVariable %_ptr_float Function\n" +
4193 "%ld = OpLoad %float %n\n" +
4194 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4195 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
4196 "OpReturn\n" +
4197 "OpFunctionEnd",
4198 2, 0),
4199 // Test case 5: Don't Fold 0.0 > clamp(-1, 1)
4200 InstructionFoldingCase<uint32_t>(
4201 Header() + "%main = OpFunction %void None %void_func\n" +
4202 "%main_lab = OpLabel\n" +
4203 "%n = OpVariable %_ptr_float Function\n" +
4204 "%ld = OpLoad %float %n\n" +
4205 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4206 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
4207 "OpReturn\n" +
4208 "OpFunctionEnd",
4209 2, 0),
4210 // Test case 6: Don't Fold 0.0 >= clamp(-1, 1)
4211 InstructionFoldingCase<uint32_t>(
4212 Header() + "%main = OpFunction %void None %void_func\n" +
4213 "%main_lab = OpLabel\n" +
4214 "%n = OpVariable %_ptr_float Function\n" +
4215 "%ld = OpLoad %float %n\n" +
4216 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4217 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
4218 "OpReturn\n" +
4219 "OpFunctionEnd",
4220 2, 0),
4221 // Test case 7: Don't Fold 0.0 >= clamp(-1, 1)
4222 InstructionFoldingCase<uint32_t>(
4223 Header() + "%main = OpFunction %void None %void_func\n" +
4224 "%main_lab = OpLabel\n" +
4225 "%n = OpVariable %_ptr_float Function\n" +
4226 "%ld = OpLoad %float %n\n" +
4227 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4228 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
4229 "OpReturn\n" +
4230 "OpFunctionEnd",
4231 2, 0),
4232 // Test case 8: Don't Fold 0.0 < clamp(0, 1)
4233 InstructionFoldingCase<uint32_t>(
4234 Header() + "%main = OpFunction %void None %void_func\n" +
4235 "%main_lab = OpLabel\n" +
4236 "%n = OpVariable %_ptr_float Function\n" +
4237 "%ld = OpLoad %float %n\n" +
4238 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
4239 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
4240 "OpReturn\n" +
4241 "OpFunctionEnd",
4242 2, 0),
4243 // Test case 9: Don't Fold 0.0 < clamp(0, 1)
4244 InstructionFoldingCase<uint32_t>(
4245 Header() + "%main = OpFunction %void None %void_func\n" +
4246 "%main_lab = OpLabel\n" +
4247 "%n = OpVariable %_ptr_float Function\n" +
4248 "%ld = OpLoad %float %n\n" +
4249 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
4250 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
4251 "OpReturn\n" +
4252 "OpFunctionEnd",
4253 2, 0),
4254 // Test case 10: Don't Fold 0.0 > clamp(-1, 0)
4255 InstructionFoldingCase<uint32_t>(
4256 Header() + "%main = OpFunction %void None %void_func\n" +
4257 "%main_lab = OpLabel\n" +
4258 "%n = OpVariable %_ptr_float Function\n" +
4259 "%ld = OpLoad %float %n\n" +
4260 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
4261 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
4262 "OpReturn\n" +
4263 "OpFunctionEnd",
4264 2, 0),
4265 // Test case 11: Don't Fold 0.0 > clamp(-1, 0)
4266 InstructionFoldingCase<uint32_t>(
4267 Header() + "%main = OpFunction %void None %void_func\n" +
4268 "%main_lab = OpLabel\n" +
4269 "%n = OpVariable %_ptr_float Function\n" +
4270 "%ld = OpLoad %float %n\n" +
4271 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
4272 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
4273 "OpReturn\n" +
4274 "OpFunctionEnd",
4275 2, 0)
4276 ));
4277
4278 INSTANTIATE_TEST_SUITE_P(ClampAndCmpRHS, GeneralInstructionFoldingTest,
4279 ::testing::Values(
4280 // Test case 0: Don't Fold clamp(-1, 1) < 0.0
4281 InstructionFoldingCase<uint32_t>(
4282 Header() + "%main = OpFunction %void None %void_func\n" +
4283 "%main_lab = OpLabel\n" +
4284 "%n = OpVariable %_ptr_float Function\n" +
4285 "%ld = OpLoad %float %n\n" +
4286 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4287 "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
4288 "OpReturn\n" +
4289 "OpFunctionEnd",
4290 2, 0),
4291 // Test case 1: Don't Fold clamp(-1, 1) < 0.0
4292 InstructionFoldingCase<uint32_t>(
4293 Header() + "%main = OpFunction %void None %void_func\n" +
4294 "%main_lab = OpLabel\n" +
4295 "%n = OpVariable %_ptr_float Function\n" +
4296 "%ld = OpLoad %float %n\n" +
4297 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4298 "%2 = OpFOrdLessThan %bool %clamp %float_0\n" +
4299 "OpReturn\n" +
4300 "OpFunctionEnd",
4301 2, 0),
4302 // Test case 2: Don't Fold clamp(-1, 1) <= 0.0
4303 InstructionFoldingCase<uint32_t>(
4304 Header() + "%main = OpFunction %void None %void_func\n" +
4305 "%main_lab = OpLabel\n" +
4306 "%n = OpVariable %_ptr_float Function\n" +
4307 "%ld = OpLoad %float %n\n" +
4308 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4309 "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
4310 "OpReturn\n" +
4311 "OpFunctionEnd",
4312 2, 0),
4313 // Test case 3: Don't Fold clamp(-1, 1) <= 0.0
4314 InstructionFoldingCase<uint32_t>(
4315 Header() + "%main = OpFunction %void None %void_func\n" +
4316 "%main_lab = OpLabel\n" +
4317 "%n = OpVariable %_ptr_float Function\n" +
4318 "%ld = OpLoad %float %n\n" +
4319 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4320 "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
4321 "OpReturn\n" +
4322 "OpFunctionEnd",
4323 2, 0),
4324 // Test case 4: Don't Fold clamp(-1, 1) > 0.0
4325 InstructionFoldingCase<uint32_t>(
4326 Header() + "%main = OpFunction %void None %void_func\n" +
4327 "%main_lab = OpLabel\n" +
4328 "%n = OpVariable %_ptr_float Function\n" +
4329 "%ld = OpLoad %float %n\n" +
4330 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4331 "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
4332 "OpReturn\n" +
4333 "OpFunctionEnd",
4334 2, 0),
4335 // Test case 5: Don't Fold clamp(-1, 1) > 0.0
4336 InstructionFoldingCase<uint32_t>(
4337 Header() + "%main = OpFunction %void None %void_func\n" +
4338 "%main_lab = OpLabel\n" +
4339 "%n = OpVariable %_ptr_float Function\n" +
4340 "%ld = OpLoad %float %n\n" +
4341 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4342 "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
4343 "OpReturn\n" +
4344 "OpFunctionEnd",
4345 2, 0),
4346 // Test case 6: Don't Fold clamp(-1, 1) >= 0.0
4347 InstructionFoldingCase<uint32_t>(
4348 Header() + "%main = OpFunction %void None %void_func\n" +
4349 "%main_lab = OpLabel\n" +
4350 "%n = OpVariable %_ptr_float Function\n" +
4351 "%ld = OpLoad %float %n\n" +
4352 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4353 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_0\n" +
4354 "OpReturn\n" +
4355 "OpFunctionEnd",
4356 2, 0),
4357 // Test case 7: Don't Fold clamp(-1, 1) >= 0.0
4358 InstructionFoldingCase<uint32_t>(
4359 Header() + "%main = OpFunction %void None %void_func\n" +
4360 "%main_lab = OpLabel\n" +
4361 "%n = OpVariable %_ptr_float Function\n" +
4362 "%ld = OpLoad %float %n\n" +
4363 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
4364 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
4365 "OpReturn\n" +
4366 "OpFunctionEnd",
4367 2, 0),
4368 // Test case 8: Don't Fold clamp(-1, 0) < 0.0
4369 InstructionFoldingCase<uint32_t>(
4370 Header() + "%main = OpFunction %void None %void_func\n" +
4371 "%main_lab = OpLabel\n" +
4372 "%n = OpVariable %_ptr_float Function\n" +
4373 "%ld = OpLoad %float %n\n" +
4374 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
4375 "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
4376 "OpReturn\n" +
4377 "OpFunctionEnd",
4378 2, 0),
4379 // Test case 9: Don't Fold clamp(0, 1) < 1
4380 InstructionFoldingCase<uint32_t>(
4381 Header() + "%main = OpFunction %void None %void_func\n" +
4382 "%main_lab = OpLabel\n" +
4383 "%n = OpVariable %_ptr_float Function\n" +
4384 "%ld = OpLoad %float %n\n" +
4385 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
4386 "%2 = OpFOrdLessThan %bool %clamp %float_1\n" +
4387 "OpReturn\n" +
4388 "OpFunctionEnd",
4389 2, 0),
4390 // Test case 10: Don't Fold clamp(-1, 0) > -1
4391 InstructionFoldingCase<uint32_t>(
4392 Header() + "%main = OpFunction %void None %void_func\n" +
4393 "%main_lab = OpLabel\n" +
4394 "%n = OpVariable %_ptr_float Function\n" +
4395 "%ld = OpLoad %float %n\n" +
4396 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
4397 "%2 = OpFUnordGreaterThan %bool %clamp %float_n1\n" +
4398 "OpReturn\n" +
4399 "OpFunctionEnd",
4400 2, 0),
4401 // Test case 11: Don't Fold clamp(-1, 0) > -1
4402 InstructionFoldingCase<uint32_t>(
4403 Header() + "%main = OpFunction %void None %void_func\n" +
4404 "%main_lab = OpLabel\n" +
4405 "%n = OpVariable %_ptr_float Function\n" +
4406 "%ld = OpLoad %float %n\n" +
4407 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
4408 "%2 = OpFOrdGreaterThan %bool %clamp %float_n1\n" +
4409 "OpReturn\n" +
4410 "OpFunctionEnd",
4411 2, 0)
4412 ));
4413
4414 INSTANTIATE_TEST_SUITE_P(FToIConstantFoldingTest, IntegerInstructionFoldingTest,
4415 ::testing::Values(
4416 // Test case 0: Fold int(3.0)
4417 InstructionFoldingCase<uint32_t>(
4418 Header() + "%main = OpFunction %void None %void_func\n" +
4419 "%main_lab = OpLabel\n" +
4420 "%2 = OpConvertFToS %int %float_3\n" +
4421 "OpReturn\n" +
4422 "OpFunctionEnd",
4423 2, 3),
4424 // Test case 1: Fold uint(3.0)
4425 InstructionFoldingCase<uint32_t>(
4426 Header() + "%main = OpFunction %void None %void_func\n" +
4427 "%main_lab = OpLabel\n" +
4428 "%2 = OpConvertFToU %int %float_3\n" +
4429 "OpReturn\n" +
4430 "OpFunctionEnd",
4431 2, 3)
4432 ));
4433
4434 INSTANTIATE_TEST_SUITE_P(IToFConstantFoldingTest, FloatInstructionFoldingTest,
4435 ::testing::Values(
4436 // Test case 0: Fold float(3)
4437 InstructionFoldingCase<float>(
4438 Header() + "%main = OpFunction %void None %void_func\n" +
4439 "%main_lab = OpLabel\n" +
4440 "%2 = OpConvertSToF %float %int_3\n" +
4441 "OpReturn\n" +
4442 "OpFunctionEnd",
4443 2, 3.0),
4444 // Test case 1: Fold float(3u)
4445 InstructionFoldingCase<float>(
4446 Header() + "%main = OpFunction %void None %void_func\n" +
4447 "%main_lab = OpLabel\n" +
4448 "%2 = OpConvertUToF %float %uint_3\n" +
4449 "OpReturn\n" +
4450 "OpFunctionEnd",
4451 2, 3.0)
4452 ));
4453 // clang-format on
4454
4455 using ToNegateFoldingTest =
4456 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
4457
TEST_P(ToNegateFoldingTest,Case)4458 TEST_P(ToNegateFoldingTest, Case) {
4459 const auto& tc = GetParam();
4460
4461 // Build module.
4462 std::unique_ptr<IRContext> context =
4463 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
4464 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4465 ASSERT_NE(nullptr, context);
4466
4467 // Fold the instruction to test.
4468 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
4469 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
4470 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
4471 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
4472
4473 // Make sure the instruction folded as expected.
4474 EXPECT_EQ(inst->result_id(), original_inst->result_id());
4475 EXPECT_EQ(inst->type_id(), original_inst->type_id());
4476 EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
4477 if (succeeded) {
4478 EXPECT_EQ(inst->opcode(), SpvOpFNegate);
4479 EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
4480 } else {
4481 EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
4482 for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
4483 EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
4484 }
4485 }
4486 }
4487
4488 // clang-format off
4489 INSTANTIATE_TEST_SUITE_P(FloatRedundantSubFoldingTest, ToNegateFoldingTest,
4490 ::testing::Values(
4491 // Test case 0: Don't fold 1.0 - n
4492 InstructionFoldingCase<uint32_t>(
4493 Header() + "%main = OpFunction %void None %void_func\n" +
4494 "%main_lab = OpLabel\n" +
4495 "%n = OpVariable %_ptr_float Function\n" +
4496 "%3 = OpLoad %float %n\n" +
4497 "%2 = OpFSub %float %float_1 %3\n" +
4498 "OpReturn\n" +
4499 "OpFunctionEnd",
4500 2, 0),
4501 // Test case 1: Fold 0.0 - n
4502 InstructionFoldingCase<uint32_t>(
4503 Header() + "%main = OpFunction %void None %void_func\n" +
4504 "%main_lab = OpLabel\n" +
4505 "%n = OpVariable %_ptr_float Function\n" +
4506 "%3 = OpLoad %float %n\n" +
4507 "%2 = OpFSub %float %float_0 %3\n" +
4508 "OpReturn\n" +
4509 "OpFunctionEnd",
4510 2, 3),
4511 // Test case 2: Don't fold (0,0,0,1) - n
4512 InstructionFoldingCase<uint32_t>(
4513 Header() + "%main = OpFunction %void None %void_func\n" +
4514 "%main_lab = OpLabel\n" +
4515 "%n = OpVariable %_ptr_v4float Function\n" +
4516 "%3 = OpLoad %v4float %n\n" +
4517 "%2 = OpFSub %v4float %v4float_0_0_0_1 %3\n" +
4518 "OpReturn\n" +
4519 "OpFunctionEnd",
4520 2, 0),
4521 // Test case 3: Fold (0,0,0,0) - n
4522 InstructionFoldingCase<uint32_t>(
4523 Header() + "%main = OpFunction %void None %void_func\n" +
4524 "%main_lab = OpLabel\n" +
4525 "%n = OpVariable %_ptr_v4float Function\n" +
4526 "%3 = OpLoad %v4float %n\n" +
4527 "%2 = OpFSub %v4float %v4float_0_0_0_0 %3\n" +
4528 "OpReturn\n" +
4529 "OpFunctionEnd",
4530 2, 3)
4531 ));
4532
4533 INSTANTIATE_TEST_SUITE_P(DoubleRedundantSubFoldingTest, ToNegateFoldingTest,
4534 ::testing::Values(
4535 // Test case 0: Don't fold 1.0 - n
4536 InstructionFoldingCase<uint32_t>(
4537 Header() + "%main = OpFunction %void None %void_func\n" +
4538 "%main_lab = OpLabel\n" +
4539 "%n = OpVariable %_ptr_double Function\n" +
4540 "%3 = OpLoad %double %n\n" +
4541 "%2 = OpFSub %double %double_1 %3\n" +
4542 "OpReturn\n" +
4543 "OpFunctionEnd",
4544 2, 0),
4545 // Test case 1: Fold 0.0 - n
4546 InstructionFoldingCase<uint32_t>(
4547 Header() + "%main = OpFunction %void None %void_func\n" +
4548 "%main_lab = OpLabel\n" +
4549 "%n = OpVariable %_ptr_double Function\n" +
4550 "%3 = OpLoad %double %n\n" +
4551 "%2 = OpFSub %double %double_0 %3\n" +
4552 "OpReturn\n" +
4553 "OpFunctionEnd",
4554 2, 3),
4555 // Test case 2: Don't fold (0,0,0,1) - n
4556 InstructionFoldingCase<uint32_t>(
4557 Header() + "%main = OpFunction %void None %void_func\n" +
4558 "%main_lab = OpLabel\n" +
4559 "%n = OpVariable %_ptr_v4double Function\n" +
4560 "%3 = OpLoad %v4double %n\n" +
4561 "%2 = OpFSub %v4double %v4double_0_0_0_1 %3\n" +
4562 "OpReturn\n" +
4563 "OpFunctionEnd",
4564 2, 0),
4565 // Test case 3: Fold (0,0,0,0) - n
4566 InstructionFoldingCase<uint32_t>(
4567 Header() + "%main = OpFunction %void None %void_func\n" +
4568 "%main_lab = OpLabel\n" +
4569 "%n = OpVariable %_ptr_v4double Function\n" +
4570 "%3 = OpLoad %v4double %n\n" +
4571 "%2 = OpFSub %v4double %v4double_0_0_0_0 %3\n" +
4572 "OpReturn\n" +
4573 "OpFunctionEnd",
4574 2, 3)
4575 ));
4576
4577 using MatchingInstructionFoldingTest =
4578 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
4579
TEST_P(MatchingInstructionFoldingTest,Case)4580 TEST_P(MatchingInstructionFoldingTest, Case) {
4581 const auto& tc = GetParam();
4582
4583 // Build module.
4584 std::unique_ptr<IRContext> context =
4585 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
4586 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
4587 ASSERT_NE(nullptr, context);
4588
4589 // Fold the instruction to test.
4590 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
4591 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
4592 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
4593 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
4594 EXPECT_EQ(succeeded, tc.expected_result);
4595 if (succeeded) {
4596 Match(tc.test_body, context.get());
4597 }
4598 }
4599
4600 INSTANTIATE_TEST_SUITE_P(RedundantIntegerMatching, MatchingInstructionFoldingTest,
4601 ::testing::Values(
4602 // Test case 0: Fold 0 + n (change sign)
4603 InstructionFoldingCase<bool>(
4604 Header() +
4605 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
4606 "; CHECK: %2 = OpBitcast [[uint]] %3\n" +
4607 "%main = OpFunction %void None %void_func\n" +
4608 "%main_lab = OpLabel\n" +
4609 "%n = OpVariable %_ptr_int Function\n" +
4610 "%3 = OpLoad %uint %n\n" +
4611 "%2 = OpIAdd %uint %int_0 %3\n" +
4612 "OpReturn\n" +
4613 "OpFunctionEnd\n",
4614 2, true),
4615 // Test case 0: Fold 0 + n (change sign)
4616 InstructionFoldingCase<bool>(
4617 Header() +
4618 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4619 "; CHECK: %2 = OpBitcast [[int]] %3\n" +
4620 "%main = OpFunction %void None %void_func\n" +
4621 "%main_lab = OpLabel\n" +
4622 "%n = OpVariable %_ptr_int Function\n" +
4623 "%3 = OpLoad %int %n\n" +
4624 "%2 = OpIAdd %int %uint_0 %3\n" +
4625 "OpReturn\n" +
4626 "OpFunctionEnd\n",
4627 2, true)
4628 ));
4629
4630 INSTANTIATE_TEST_SUITE_P(MergeNegateTest, MatchingInstructionFoldingTest,
4631 ::testing::Values(
4632 // Test case 0: fold consecutive fnegate
4633 // -(-x) = x
4634 InstructionFoldingCase<bool>(
4635 Header() +
4636 "; CHECK: [[ld:%\\w+]] = OpLoad [[float:%\\w+]]\n" +
4637 "; CHECK: %4 = OpCopyObject [[float]] [[ld]]\n" +
4638 "%main = OpFunction %void None %void_func\n" +
4639 "%main_lab = OpLabel\n" +
4640 "%var = OpVariable %_ptr_float Function\n" +
4641 "%2 = OpLoad %float %var\n" +
4642 "%3 = OpFNegate %float %2\n" +
4643 "%4 = OpFNegate %float %3\n" +
4644 "OpReturn\n" +
4645 "OpFunctionEnd",
4646 4, true),
4647 // Test case 1: fold fnegate(fmul with const).
4648 // -(x * 2.0) = x * -2.0
4649 InstructionFoldingCase<bool>(
4650 Header() +
4651 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4652 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
4653 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4654 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
4655 "%main = OpFunction %void None %void_func\n" +
4656 "%main_lab = OpLabel\n" +
4657 "%var = OpVariable %_ptr_float Function\n" +
4658 "%2 = OpLoad %float %var\n" +
4659 "%3 = OpFMul %float %2 %float_2\n" +
4660 "%4 = OpFNegate %float %3\n" +
4661 "OpReturn\n" +
4662 "OpFunctionEnd",
4663 4, true),
4664 // Test case 2: fold fnegate(fmul with const).
4665 // -(2.0 * x) = x * 2.0
4666 InstructionFoldingCase<bool>(
4667 Header() +
4668 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4669 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
4670 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4671 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
4672 "%main = OpFunction %void None %void_func\n" +
4673 "%main_lab = OpLabel\n" +
4674 "%var = OpVariable %_ptr_float Function\n" +
4675 "%2 = OpLoad %float %var\n" +
4676 "%3 = OpFMul %float %float_2 %2\n" +
4677 "%4 = OpFNegate %float %3\n" +
4678 "OpReturn\n" +
4679 "OpFunctionEnd",
4680 4, true),
4681 // Test case 3: fold fnegate(fdiv with const).
4682 // -(x / 2.0) = x * -0.5
4683 InstructionFoldingCase<bool>(
4684 Header() +
4685 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4686 "; CHECK: [[float_n0p5:%\\w+]] = OpConstant [[float]] -0.5\n" +
4687 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4688 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n0p5]]\n" +
4689 "%main = OpFunction %void None %void_func\n" +
4690 "%main_lab = OpLabel\n" +
4691 "%var = OpVariable %_ptr_float Function\n" +
4692 "%2 = OpLoad %float %var\n" +
4693 "%3 = OpFDiv %float %2 %float_2\n" +
4694 "%4 = OpFNegate %float %3\n" +
4695 "OpReturn\n" +
4696 "OpFunctionEnd",
4697 4, true),
4698 // Test case 4: fold fnegate(fdiv with const).
4699 // -(2.0 / x) = -2.0 / x
4700 InstructionFoldingCase<bool>(
4701 Header() +
4702 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4703 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
4704 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4705 "; CHECK: %4 = OpFDiv [[float]] [[float_n2]] [[ld]]\n" +
4706 "%main = OpFunction %void None %void_func\n" +
4707 "%main_lab = OpLabel\n" +
4708 "%var = OpVariable %_ptr_float Function\n" +
4709 "%2 = OpLoad %float %var\n" +
4710 "%3 = OpFDiv %float %float_2 %2\n" +
4711 "%4 = OpFNegate %float %3\n" +
4712 "OpReturn\n" +
4713 "OpFunctionEnd",
4714 4, true),
4715 // Test case 5: fold fnegate(fadd with const).
4716 // -(2.0 + x) = -2.0 - x
4717 InstructionFoldingCase<bool>(
4718 Header() +
4719 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4720 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
4721 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4722 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
4723 "%main = OpFunction %void None %void_func\n" +
4724 "%main_lab = OpLabel\n" +
4725 "%var = OpVariable %_ptr_float Function\n" +
4726 "%2 = OpLoad %float %var\n" +
4727 "%3 = OpFAdd %float %float_2 %2\n" +
4728 "%4 = OpFNegate %float %3\n" +
4729 "OpReturn\n" +
4730 "OpFunctionEnd",
4731 4, true),
4732 // Test case 6: fold fnegate(fadd with const).
4733 // -(x + 2.0) = -2.0 - x
4734 InstructionFoldingCase<bool>(
4735 Header() +
4736 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4737 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
4738 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4739 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
4740 "%main = OpFunction %void None %void_func\n" +
4741 "%main_lab = OpLabel\n" +
4742 "%var = OpVariable %_ptr_float Function\n" +
4743 "%2 = OpLoad %float %var\n" +
4744 "%3 = OpFAdd %float %2 %float_2\n" +
4745 "%4 = OpFNegate %float %3\n" +
4746 "OpReturn\n" +
4747 "OpFunctionEnd",
4748 4, true),
4749 // Test case 7: fold fnegate(fsub with const).
4750 // -(2.0 - x) = x - 2.0
4751 InstructionFoldingCase<bool>(
4752 Header() +
4753 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4754 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4755 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4756 "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_2]]\n" +
4757 "%main = OpFunction %void None %void_func\n" +
4758 "%main_lab = OpLabel\n" +
4759 "%var = OpVariable %_ptr_float Function\n" +
4760 "%2 = OpLoad %float %var\n" +
4761 "%3 = OpFSub %float %float_2 %2\n" +
4762 "%4 = OpFNegate %float %3\n" +
4763 "OpReturn\n" +
4764 "OpFunctionEnd",
4765 4, true),
4766 // Test case 8: fold fnegate(fsub with const).
4767 // -(x - 2.0) = 2.0 - x
4768 InstructionFoldingCase<bool>(
4769 Header() +
4770 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4771 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4772 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4773 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
4774 "%main = OpFunction %void None %void_func\n" +
4775 "%main_lab = OpLabel\n" +
4776 "%var = OpVariable %_ptr_float Function\n" +
4777 "%2 = OpLoad %float %var\n" +
4778 "%3 = OpFSub %float %2 %float_2\n" +
4779 "%4 = OpFNegate %float %3\n" +
4780 "OpReturn\n" +
4781 "OpFunctionEnd",
4782 4, true),
4783 // Test case 9: fold consecutive snegate
4784 // -(-x) = x
4785 InstructionFoldingCase<bool>(
4786 Header() +
4787 "; CHECK: [[ld:%\\w+]] = OpLoad [[int:%\\w+]]\n" +
4788 "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
4789 "%main = OpFunction %void None %void_func\n" +
4790 "%main_lab = OpLabel\n" +
4791 "%var = OpVariable %_ptr_int Function\n" +
4792 "%2 = OpLoad %int %var\n" +
4793 "%3 = OpSNegate %int %2\n" +
4794 "%4 = OpSNegate %int %3\n" +
4795 "OpReturn\n" +
4796 "OpFunctionEnd",
4797 4, true),
4798 // Test case 10: fold consecutive vector negate
4799 // -(-x) = x
4800 InstructionFoldingCase<bool>(
4801 Header() +
4802 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float:%\\w+]]\n" +
4803 "; CHECK: %4 = OpCopyObject [[v2float]] [[ld]]\n" +
4804 "%main = OpFunction %void None %void_func\n" +
4805 "%main_lab = OpLabel\n" +
4806 "%var = OpVariable %_ptr_v2float Function\n" +
4807 "%2 = OpLoad %v2float %var\n" +
4808 "%3 = OpFNegate %v2float %2\n" +
4809 "%4 = OpFNegate %v2float %3\n" +
4810 "OpReturn\n" +
4811 "OpFunctionEnd",
4812 4, true),
4813 // Test case 11: fold snegate(iadd with const).
4814 // -(2 + x) = -2 - x
4815 InstructionFoldingCase<bool>(
4816 Header() +
4817 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4818 "; CHECK: OpConstant [[int]] -2147483648\n" +
4819 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
4820 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
4821 "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
4822 "%main = OpFunction %void None %void_func\n" +
4823 "%main_lab = OpLabel\n" +
4824 "%var = OpVariable %_ptr_int Function\n" +
4825 "%2 = OpLoad %int %var\n" +
4826 "%3 = OpIAdd %int %int_2 %2\n" +
4827 "%4 = OpSNegate %int %3\n" +
4828 "OpReturn\n" +
4829 "OpFunctionEnd",
4830 4, true),
4831 // Test case 12: fold snegate(iadd with const).
4832 // -(x + 2) = -2 - x
4833 InstructionFoldingCase<bool>(
4834 Header() +
4835 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4836 "; CHECK: OpConstant [[int]] -2147483648\n" +
4837 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
4838 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
4839 "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
4840 "%main = OpFunction %void None %void_func\n" +
4841 "%main_lab = OpLabel\n" +
4842 "%var = OpVariable %_ptr_int Function\n" +
4843 "%2 = OpLoad %int %var\n" +
4844 "%3 = OpIAdd %int %2 %int_2\n" +
4845 "%4 = OpSNegate %int %3\n" +
4846 "OpReturn\n" +
4847 "OpFunctionEnd",
4848 4, true),
4849 // Test case 13: fold snegate(isub with const).
4850 // -(2 - x) = x - 2
4851 InstructionFoldingCase<bool>(
4852 Header() +
4853 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4854 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
4855 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
4856 "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_2]]\n" +
4857 "%main = OpFunction %void None %void_func\n" +
4858 "%main_lab = OpLabel\n" +
4859 "%var = OpVariable %_ptr_int Function\n" +
4860 "%2 = OpLoad %int %var\n" +
4861 "%3 = OpISub %int %int_2 %2\n" +
4862 "%4 = OpSNegate %int %3\n" +
4863 "OpReturn\n" +
4864 "OpFunctionEnd",
4865 4, true),
4866 // Test case 14: fold snegate(isub with const).
4867 // -(x - 2) = 2 - x
4868 InstructionFoldingCase<bool>(
4869 Header() +
4870 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4871 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
4872 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
4873 "; CHECK: %4 = OpISub [[int]] [[int_2]] [[ld]]\n" +
4874 "%main = OpFunction %void None %void_func\n" +
4875 "%main_lab = OpLabel\n" +
4876 "%var = OpVariable %_ptr_int Function\n" +
4877 "%2 = OpLoad %int %var\n" +
4878 "%3 = OpISub %int %2 %int_2\n" +
4879 "%4 = OpSNegate %int %3\n" +
4880 "OpReturn\n" +
4881 "OpFunctionEnd",
4882 4, true),
4883 // Test case 15: fold snegate(iadd with const).
4884 // -(x + 2) = -2 - x
4885 InstructionFoldingCase<bool>(
4886 Header() +
4887 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
4888 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
4889 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
4890 "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
4891 "%main = OpFunction %void None %void_func\n" +
4892 "%main_lab = OpLabel\n" +
4893 "%var = OpVariable %_ptr_long Function\n" +
4894 "%2 = OpLoad %long %var\n" +
4895 "%3 = OpIAdd %long %2 %long_2\n" +
4896 "%4 = OpSNegate %long %3\n" +
4897 "OpReturn\n" +
4898 "OpFunctionEnd",
4899 4, true),
4900 // Test case 16: fold snegate(isub with const).
4901 // -(2 - x) = x - 2
4902 InstructionFoldingCase<bool>(
4903 Header() +
4904 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
4905 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
4906 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
4907 "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_2]]\n" +
4908 "%main = OpFunction %void None %void_func\n" +
4909 "%main_lab = OpLabel\n" +
4910 "%var = OpVariable %_ptr_long Function\n" +
4911 "%2 = OpLoad %long %var\n" +
4912 "%3 = OpISub %long %long_2 %2\n" +
4913 "%4 = OpSNegate %long %3\n" +
4914 "OpReturn\n" +
4915 "OpFunctionEnd",
4916 4, true),
4917 // Test case 17: fold snegate(isub with const).
4918 // -(x - 2) = 2 - x
4919 InstructionFoldingCase<bool>(
4920 Header() +
4921 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
4922 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
4923 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
4924 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
4925 "%main = OpFunction %void None %void_func\n" +
4926 "%main_lab = OpLabel\n" +
4927 "%var = OpVariable %_ptr_long Function\n" +
4928 "%2 = OpLoad %long %var\n" +
4929 "%3 = OpISub %long %2 %long_2\n" +
4930 "%4 = OpSNegate %long %3\n" +
4931 "OpReturn\n" +
4932 "OpFunctionEnd",
4933 4, true),
4934 // Test case 18: fold -vec4(-1.0, 2.0, 1.0, 3.0)
4935 InstructionFoldingCase<bool>(
4936 Header() +
4937 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4938 "; CHECK: [[v4float:%\\w+]] = OpTypeVector [[float]] 4{{[[:space:]]}}\n" +
4939 "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1{{[[:space:]]}}\n" +
4940 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1{{[[:space:]]}}\n" +
4941 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
4942 "; CHECK: [[float_n3:%\\w+]] = OpConstant [[float]] -3{{[[:space:]]}}\n" +
4943 "; CHECK: [[v4float_1_n2_n1_n3:%\\w+]] = OpConstantComposite [[v4float]] [[float_1]] [[float_n2]] [[float_n1]] [[float_n3]]\n" +
4944 "; CHECK: %2 = OpCopyObject [[v4float]] [[v4float_1_n2_n1_n3]]\n" +
4945 "%main = OpFunction %void None %void_func\n" +
4946 "%main_lab = OpLabel\n" +
4947 "%2 = OpFNegate %v4float %v4float_n1_2_1_3\n" +
4948 "OpReturn\n" +
4949 "OpFunctionEnd",
4950 2, true),
4951 // Test case 19: fold vector fnegate with null
4952 InstructionFoldingCase<bool>(
4953 Header() +
4954 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
4955 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
4956 "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" +
4957 "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_n0]] [[double_n0]]\n" +
4958 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
4959 "%main = OpFunction %void None %void_func\n" +
4960 "%main_lab = OpLabel\n" +
4961 "%2 = OpFNegate %v2double %v2double_null\n" +
4962 "OpReturn\n" +
4963 "OpFunctionEnd",
4964 2, true)
4965 ));
4966
4967 INSTANTIATE_TEST_SUITE_P(ReciprocalFDivTest, MatchingInstructionFoldingTest,
4968 ::testing::Values(
4969 // Test case 0: scalar reicprocal
4970 // x / 0.5 = x * 2.0
4971 InstructionFoldingCase<bool>(
4972 Header() +
4973 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4974 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4975 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4976 "; CHECK: %3 = OpFMul [[float]] [[ld]] [[float_2]]\n" +
4977 "%main = OpFunction %void None %void_func\n" +
4978 "%main_lab = OpLabel\n" +
4979 "%var = OpVariable %_ptr_float Function\n" +
4980 "%2 = OpLoad %float %var\n" +
4981 "%3 = OpFDiv %float %2 %float_0p5\n" +
4982 "OpReturn\n" +
4983 "OpFunctionEnd\n",
4984 3, true),
4985 // Test case 1: Unfoldable
4986 InstructionFoldingCase<bool>(
4987 Header() +
4988 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4989 "; CHECK: [[float_0:%\\w+]] = OpConstant [[float]] 0\n" +
4990 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4991 "; CHECK: %3 = OpFDiv [[float]] [[ld]] [[float_0]]\n" +
4992 "%main = OpFunction %void None %void_func\n" +
4993 "%main_lab = OpLabel\n" +
4994 "%var = OpVariable %_ptr_float Function\n" +
4995 "%2 = OpLoad %float %var\n" +
4996 "%3 = OpFDiv %float %2 %104\n" +
4997 "OpReturn\n" +
4998 "OpFunctionEnd\n",
4999 3, false),
5000 // Test case 2: Vector reciprocal
5001 // x / {2.0, 0.5} = x * {0.5, 2.0}
5002 InstructionFoldingCase<bool>(
5003 Header() +
5004 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5005 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
5006 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5007 "; CHECK: [[float_0p5:%\\w+]] = OpConstant [[float]] 0.5\n" +
5008 "; CHECK: [[v2float_0p5_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_0p5]] [[float_2]]\n" +
5009 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
5010 "; CHECK: %3 = OpFMul [[v2float]] [[ld]] [[v2float_0p5_2]]\n" +
5011 "%main = OpFunction %void None %void_func\n" +
5012 "%main_lab = OpLabel\n" +
5013 "%var = OpVariable %_ptr_v2float Function\n" +
5014 "%2 = OpLoad %v2float %var\n" +
5015 "%3 = OpFDiv %v2float %2 %v2float_2_0p5\n" +
5016 "OpReturn\n" +
5017 "OpFunctionEnd\n",
5018 3, true),
5019 // Test case 3: double reciprocal
5020 // x / 2.0 = x * 0.5
5021 InstructionFoldingCase<bool>(
5022 Header() +
5023 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5024 "; CHECK: [[double_0p5:%\\w+]] = OpConstant [[double]] 0.5\n" +
5025 "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
5026 "; CHECK: %3 = OpFMul [[double]] [[ld]] [[double_0p5]]\n" +
5027 "%main = OpFunction %void None %void_func\n" +
5028 "%main_lab = OpLabel\n" +
5029 "%var = OpVariable %_ptr_double Function\n" +
5030 "%2 = OpLoad %double %var\n" +
5031 "%3 = OpFDiv %double %2 %double_2\n" +
5032 "OpReturn\n" +
5033 "OpFunctionEnd\n",
5034 3, true),
5035 // Test case 4: don't fold x / 0.
5036 InstructionFoldingCase<bool>(
5037 Header() +
5038 "%main = OpFunction %void None %void_func\n" +
5039 "%main_lab = OpLabel\n" +
5040 "%var = OpVariable %_ptr_v2float Function\n" +
5041 "%2 = OpLoad %v2float %var\n" +
5042 "%3 = OpFDiv %v2float %2 %v2float_null\n" +
5043 "OpReturn\n" +
5044 "OpFunctionEnd\n",
5045 3, false)
5046 ));
5047
5048 INSTANTIATE_TEST_SUITE_P(MergeMulTest, MatchingInstructionFoldingTest,
5049 ::testing::Values(
5050 // Test case 0: fold consecutive fmuls
5051 // (x * 3.0) * 2.0 = x * 6.0
5052 InstructionFoldingCase<bool>(
5053 Header() +
5054 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5055 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5056 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5057 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
5058 "%main = OpFunction %void None %void_func\n" +
5059 "%main_lab = OpLabel\n" +
5060 "%var = OpVariable %_ptr_float Function\n" +
5061 "%2 = OpLoad %float %var\n" +
5062 "%3 = OpFMul %float %2 %float_3\n" +
5063 "%4 = OpFMul %float %3 %float_2\n" +
5064 "OpReturn\n" +
5065 "OpFunctionEnd\n",
5066 4, true),
5067 // Test case 1: fold consecutive fmuls
5068 // 2.0 * (x * 3.0) = x * 6.0
5069 InstructionFoldingCase<bool>(
5070 Header() +
5071 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5072 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5073 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5074 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
5075 "%main = OpFunction %void None %void_func\n" +
5076 "%main_lab = OpLabel\n" +
5077 "%var = OpVariable %_ptr_float Function\n" +
5078 "%2 = OpLoad %float %var\n" +
5079 "%3 = OpFMul %float %2 %float_3\n" +
5080 "%4 = OpFMul %float %float_2 %3\n" +
5081 "OpReturn\n" +
5082 "OpFunctionEnd\n",
5083 4, true),
5084 // Test case 2: fold consecutive fmuls
5085 // (3.0 * x) * 2.0 = x * 6.0
5086 InstructionFoldingCase<bool>(
5087 Header() +
5088 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5089 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5090 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5091 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
5092 "%main = OpFunction %void None %void_func\n" +
5093 "%main_lab = OpLabel\n" +
5094 "%var = OpVariable %_ptr_float Function\n" +
5095 "%2 = OpLoad %float %var\n" +
5096 "%3 = OpFMul %float %float_3 %2\n" +
5097 "%4 = OpFMul %float %float_2 %3\n" +
5098 "OpReturn\n" +
5099 "OpFunctionEnd\n",
5100 4, true),
5101 // Test case 3: fold vector fmul
5102 InstructionFoldingCase<bool>(
5103 Header() +
5104 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5105 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
5106 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
5107 "; CHECK: [[v2float_6_6:%\\w+]] = OpConstantComposite [[v2float]] [[float_6]] [[float_6]]\n" +
5108 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
5109 "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_6_6]]\n" +
5110 "%main = OpFunction %void None %void_func\n" +
5111 "%main_lab = OpLabel\n" +
5112 "%var = OpVariable %_ptr_v2float Function\n" +
5113 "%2 = OpLoad %v2float %var\n" +
5114 "%3 = OpFMul %v2float %2 %v2float_2_3\n" +
5115 "%4 = OpFMul %v2float %3 %v2float_3_2\n" +
5116 "OpReturn\n" +
5117 "OpFunctionEnd\n",
5118 4, true),
5119 // Test case 4: fold double fmuls
5120 // (x * 3.0) * 2.0 = x * 6.0
5121 InstructionFoldingCase<bool>(
5122 Header() +
5123 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5124 "; CHECK: [[double_6:%\\w+]] = OpConstant [[double]] 6\n" +
5125 "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
5126 "; CHECK: %4 = OpFMul [[double]] [[ld]] [[double_6]]\n" +
5127 "%main = OpFunction %void None %void_func\n" +
5128 "%main_lab = OpLabel\n" +
5129 "%var = OpVariable %_ptr_double Function\n" +
5130 "%2 = OpLoad %double %var\n" +
5131 "%3 = OpFMul %double %2 %double_3\n" +
5132 "%4 = OpFMul %double %3 %double_2\n" +
5133 "OpReturn\n" +
5134 "OpFunctionEnd\n",
5135 4, true),
5136 // Test case 5: fold 32 bit imuls
5137 // (x * 3) * 2 = x * 6
5138 InstructionFoldingCase<bool>(
5139 Header() +
5140 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5141 "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
5142 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5143 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_6]]\n" +
5144 "%main = OpFunction %void None %void_func\n" +
5145 "%main_lab = OpLabel\n" +
5146 "%var = OpVariable %_ptr_int Function\n" +
5147 "%2 = OpLoad %int %var\n" +
5148 "%3 = OpIMul %int %2 %int_3\n" +
5149 "%4 = OpIMul %int %3 %int_2\n" +
5150 "OpReturn\n" +
5151 "OpFunctionEnd\n",
5152 4, true),
5153 // Test case 6: fold 64 bit imuls
5154 // (x * 3) * 2 = x * 6
5155 InstructionFoldingCase<bool>(
5156 Header() +
5157 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
5158 "; CHECK: [[long_6:%\\w+]] = OpConstant [[long]] 6\n" +
5159 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5160 "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_6]]\n" +
5161 "%main = OpFunction %void None %void_func\n" +
5162 "%main_lab = OpLabel\n" +
5163 "%var = OpVariable %_ptr_long Function\n" +
5164 "%2 = OpLoad %long %var\n" +
5165 "%3 = OpIMul %long %2 %long_3\n" +
5166 "%4 = OpIMul %long %3 %long_2\n" +
5167 "OpReturn\n" +
5168 "OpFunctionEnd\n",
5169 4, true),
5170 // Test case 7: merge vector integer mults
5171 InstructionFoldingCase<bool>(
5172 Header() +
5173 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5174 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
5175 "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
5176 "; CHECK: [[v2int_6_6:%\\w+]] = OpConstantComposite [[v2int]] [[int_6]] [[int_6]]\n" +
5177 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
5178 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_6_6]]\n" +
5179 "%main = OpFunction %void None %void_func\n" +
5180 "%main_lab = OpLabel\n" +
5181 "%var = OpVariable %_ptr_v2int Function\n" +
5182 "%2 = OpLoad %v2int %var\n" +
5183 "%3 = OpIMul %v2int %2 %v2int_2_3\n" +
5184 "%4 = OpIMul %v2int %3 %v2int_3_2\n" +
5185 "OpReturn\n" +
5186 "OpFunctionEnd\n",
5187 4, true),
5188 // Test case 8: merge fmul of fdiv
5189 // 2.0 * (2.0 / x) = 4.0 / x
5190 InstructionFoldingCase<bool>(
5191 Header() +
5192 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5193 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
5194 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5195 "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
5196 "%main = OpFunction %void None %void_func\n" +
5197 "%main_lab = OpLabel\n" +
5198 "%var = OpVariable %_ptr_float Function\n" +
5199 "%2 = OpLoad %float %var\n" +
5200 "%3 = OpFDiv %float %float_2 %2\n" +
5201 "%4 = OpFMul %float %float_2 %3\n" +
5202 "OpReturn\n" +
5203 "OpFunctionEnd\n",
5204 4, true),
5205 // Test case 9: merge fmul of fdiv
5206 // (2.0 / x) * 2.0 = 4.0 / x
5207 InstructionFoldingCase<bool>(
5208 Header() +
5209 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5210 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
5211 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5212 "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
5213 "%main = OpFunction %void None %void_func\n" +
5214 "%main_lab = OpLabel\n" +
5215 "%var = OpVariable %_ptr_float Function\n" +
5216 "%2 = OpLoad %float %var\n" +
5217 "%3 = OpFDiv %float %float_2 %2\n" +
5218 "%4 = OpFMul %float %3 %float_2\n" +
5219 "OpReturn\n" +
5220 "OpFunctionEnd\n",
5221 4, true),
5222 // Test case 10: Do not merge imul of sdiv
5223 // 4 * (x / 2)
5224 InstructionFoldingCase<bool>(
5225 Header() +
5226 "%main = OpFunction %void None %void_func\n" +
5227 "%main_lab = OpLabel\n" +
5228 "%var = OpVariable %_ptr_int Function\n" +
5229 "%2 = OpLoad %int %var\n" +
5230 "%3 = OpSDiv %int %2 %int_2\n" +
5231 "%4 = OpIMul %int %int_4 %3\n" +
5232 "OpReturn\n" +
5233 "OpFunctionEnd\n",
5234 4, false),
5235 // Test case 11: Do not merge imul of sdiv
5236 // (x / 2) * 4
5237 InstructionFoldingCase<bool>(
5238 Header() +
5239 "%main = OpFunction %void None %void_func\n" +
5240 "%main_lab = OpLabel\n" +
5241 "%var = OpVariable %_ptr_int Function\n" +
5242 "%2 = OpLoad %int %var\n" +
5243 "%3 = OpSDiv %int %2 %int_2\n" +
5244 "%4 = OpIMul %int %3 %int_4\n" +
5245 "OpReturn\n" +
5246 "OpFunctionEnd\n",
5247 4, false),
5248 // Test case 12: Do not merge imul of udiv
5249 // 4 * (x / 2)
5250 InstructionFoldingCase<bool>(
5251 Header() +
5252 "%main = OpFunction %void None %void_func\n" +
5253 "%main_lab = OpLabel\n" +
5254 "%var = OpVariable %_ptr_uint Function\n" +
5255 "%2 = OpLoad %uint %var\n" +
5256 "%3 = OpUDiv %uint %2 %uint_2\n" +
5257 "%4 = OpIMul %uint %uint_4 %3\n" +
5258 "OpReturn\n" +
5259 "OpFunctionEnd\n",
5260 4, false),
5261 // Test case 13: Do not merge imul of udiv
5262 // (x / 2) * 4
5263 InstructionFoldingCase<bool>(
5264 Header() +
5265 "%main = OpFunction %void None %void_func\n" +
5266 "%main_lab = OpLabel\n" +
5267 "%var = OpVariable %_ptr_uint Function\n" +
5268 "%2 = OpLoad %uint %var\n" +
5269 "%3 = OpUDiv %uint %2 %uint_2\n" +
5270 "%4 = OpIMul %uint %3 %uint_4\n" +
5271 "OpReturn\n" +
5272 "OpFunctionEnd\n",
5273 4, false),
5274 // Test case 14: Don't fold
5275 // (x / 3) * 4
5276 InstructionFoldingCase<bool>(
5277 Header() +
5278 "%main = OpFunction %void None %void_func\n" +
5279 "%main_lab = OpLabel\n" +
5280 "%var = OpVariable %_ptr_uint Function\n" +
5281 "%2 = OpLoad %uint %var\n" +
5282 "%3 = OpUDiv %uint %2 %uint_3\n" +
5283 "%4 = OpIMul %uint %3 %uint_4\n" +
5284 "OpReturn\n" +
5285 "OpFunctionEnd\n",
5286 4, false),
5287 // Test case 15: merge vector fmul of fdiv
5288 // (x / {2,2}) * {4,4} = x * {2,2}
5289 InstructionFoldingCase<bool>(
5290 Header() +
5291 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5292 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
5293 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5294 "; CHECK: [[v2float_2_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_2]] [[float_2]]\n" +
5295 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
5296 "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_2_2]]\n" +
5297 "%main = OpFunction %void None %void_func\n" +
5298 "%main_lab = OpLabel\n" +
5299 "%var = OpVariable %_ptr_v2float Function\n" +
5300 "%2 = OpLoad %v2float %var\n" +
5301 "%3 = OpFDiv %v2float %2 %v2float_2_2\n" +
5302 "%4 = OpFMul %v2float %3 %v2float_4_4\n" +
5303 "OpReturn\n" +
5304 "OpFunctionEnd\n",
5305 4, true),
5306 // Test case 16: merge vector imul of snegate
5307 // (-x) * {2,2} = x * {-2,-2}
5308 InstructionFoldingCase<bool>(
5309 Header() +
5310 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5311 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
5312 "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
5313 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
5314 "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
5315 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
5316 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
5317 "%main = OpFunction %void None %void_func\n" +
5318 "%main_lab = OpLabel\n" +
5319 "%var = OpVariable %_ptr_v2int Function\n" +
5320 "%2 = OpLoad %v2int %var\n" +
5321 "%3 = OpSNegate %v2int %2\n" +
5322 "%4 = OpIMul %v2int %3 %v2int_2_2\n" +
5323 "OpReturn\n" +
5324 "OpFunctionEnd\n",
5325 4, true),
5326 // Test case 17: merge vector imul of snegate
5327 // {2,2} * (-x) = x * {-2,-2}
5328 InstructionFoldingCase<bool>(
5329 Header() +
5330 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5331 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
5332 "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
5333 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
5334 "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
5335 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
5336 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
5337 "%main = OpFunction %void None %void_func\n" +
5338 "%main_lab = OpLabel\n" +
5339 "%var = OpVariable %_ptr_v2int Function\n" +
5340 "%2 = OpLoad %v2int %var\n" +
5341 "%3 = OpSNegate %v2int %2\n" +
5342 "%4 = OpIMul %v2int %v2int_2_2 %3\n" +
5343 "OpReturn\n" +
5344 "OpFunctionEnd\n",
5345 4, true),
5346 // Test case 18: Fold OpVectorTimesScalar
5347 // {4,4} = OpVectorTimesScalar v2float {2,2} 2
5348 InstructionFoldingCase<bool>(
5349 Header() +
5350 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5351 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
5352 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
5353 "; CHECK: [[v2float_4_4:%\\w+]] = OpConstantComposite [[v2float]] [[float_4]] [[float_4]]\n" +
5354 "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_4_4]]\n" +
5355 "%main = OpFunction %void None %void_func\n" +
5356 "%main_lab = OpLabel\n" +
5357 "%2 = OpVectorTimesScalar %v2float %v2float_2_2 %float_2\n" +
5358 "OpReturn\n" +
5359 "OpFunctionEnd",
5360 2, true),
5361 // Test case 19: Fold OpVectorTimesScalar
5362 // {0,0} = OpVectorTimesScalar v2float v2float_null -1
5363 InstructionFoldingCase<bool>(
5364 Header() +
5365 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5366 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
5367 "; CHECK: [[v2float_null:%\\w+]] = OpConstantNull [[v2float]]\n" +
5368 "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_null]]\n" +
5369 "%main = OpFunction %void None %void_func\n" +
5370 "%main_lab = OpLabel\n" +
5371 "%2 = OpVectorTimesScalar %v2float %v2float_null %float_n1\n" +
5372 "OpReturn\n" +
5373 "OpFunctionEnd",
5374 2, true),
5375 // Test case 20: Fold OpVectorTimesScalar
5376 // {4,4} = OpVectorTimesScalar v2double {2,2} 2
5377 InstructionFoldingCase<bool>(
5378 Header() +
5379 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5380 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
5381 "; CHECK: [[double_4:%\\w+]] = OpConstant [[double]] 4\n" +
5382 "; CHECK: [[v2double_4_4:%\\w+]] = OpConstantComposite [[v2double]] [[double_4]] [[double_4]]\n" +
5383 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_4_4]]\n" +
5384 "%main = OpFunction %void None %void_func\n" +
5385 "%main_lab = OpLabel\n" +
5386 "%2 = OpVectorTimesScalar %v2double %v2double_2_2 %double_2\n" +
5387 "OpReturn\n" +
5388 "OpFunctionEnd",
5389 2, true),
5390 // Test case 21: Fold OpVectorTimesScalar
5391 // {0,0} = OpVectorTimesScalar v2double {0,0} n
5392 InstructionFoldingCase<bool>(
5393 Header() +
5394 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5395 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
5396 "; CHECK: {{%\\w+}} = OpConstant [[double]] 0\n" +
5397 "; CHECK: [[double_0:%\\w+]] = OpConstant [[double]] 0\n" +
5398 "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_0]] [[double_0]]\n" +
5399 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
5400 "%main = OpFunction %void None %void_func\n" +
5401 "%main_lab = OpLabel\n" +
5402 "%n = OpVariable %_ptr_double Function\n" +
5403 "%load = OpLoad %double %n\n" +
5404 "%2 = OpVectorTimesScalar %v2double %v2double_0_0 %load\n" +
5405 "OpReturn\n" +
5406 "OpFunctionEnd",
5407 2, true),
5408 // Test case 22: Fold OpVectorTimesScalar
5409 // {0,0} = OpVectorTimesScalar v2double n 0
5410 InstructionFoldingCase<bool>(
5411 Header() +
5412 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5413 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
5414 "; CHECK: [[v2double_null:%\\w+]] = OpConstantNull [[v2double]]\n" +
5415 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_null]]\n" +
5416 "%main = OpFunction %void None %void_func\n" +
5417 "%main_lab = OpLabel\n" +
5418 "%n = OpVariable %_ptr_v2double Function\n" +
5419 "%load = OpLoad %v2double %n\n" +
5420 "%2 = OpVectorTimesScalar %v2double %load %double_0\n" +
5421 "OpReturn\n" +
5422 "OpFunctionEnd",
5423 2, true),
5424 // Test case 23: merge fmul of fdiv
5425 // x * (y / x) = y
5426 InstructionFoldingCase<bool>(
5427 Header() +
5428 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5429 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
5430 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
5431 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
5432 "%main = OpFunction %void None %void_func\n" +
5433 "%main_lab = OpLabel\n" +
5434 "%x = OpVariable %_ptr_float Function\n" +
5435 "%y = OpVariable %_ptr_float Function\n" +
5436 "%2 = OpLoad %float %x\n" +
5437 "%3 = OpLoad %float %y\n" +
5438 "%4 = OpFDiv %float %3 %2\n" +
5439 "%5 = OpFMul %float %2 %4\n" +
5440 "OpReturn\n" +
5441 "OpFunctionEnd\n",
5442 5, true),
5443 // Test case 24: merge fmul of fdiv
5444 // (y / x) * x = y
5445 InstructionFoldingCase<bool>(
5446 Header() +
5447 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5448 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
5449 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
5450 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
5451 "%main = OpFunction %void None %void_func\n" +
5452 "%main_lab = OpLabel\n" +
5453 "%x = OpVariable %_ptr_float Function\n" +
5454 "%y = OpVariable %_ptr_float Function\n" +
5455 "%2 = OpLoad %float %x\n" +
5456 "%3 = OpLoad %float %y\n" +
5457 "%4 = OpFDiv %float %3 %2\n" +
5458 "%5 = OpFMul %float %4 %2\n" +
5459 "OpReturn\n" +
5460 "OpFunctionEnd\n",
5461 5, true)
5462 ));
5463
5464 INSTANTIATE_TEST_SUITE_P(MergeDivTest, MatchingInstructionFoldingTest,
5465 ::testing::Values(
5466 // Test case 0: merge consecutive fdiv
5467 // 4.0 / (2.0 / x) = 2.0 * x
5468 InstructionFoldingCase<bool>(
5469 Header() +
5470 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5471 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5472 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5473 "; CHECK: %4 = OpFMul [[float]] [[float_2]] [[ld]]\n" +
5474 "%main = OpFunction %void None %void_func\n" +
5475 "%main_lab = OpLabel\n" +
5476 "%var = OpVariable %_ptr_float Function\n" +
5477 "%2 = OpLoad %float %var\n" +
5478 "%3 = OpFDiv %float %float_2 %2\n" +
5479 "%4 = OpFDiv %float %float_4 %3\n" +
5480 "OpReturn\n" +
5481 "OpFunctionEnd\n",
5482 4, true),
5483 // Test case 1: merge consecutive fdiv
5484 // 4.0 / (x / 2.0) = 8.0 / x
5485 InstructionFoldingCase<bool>(
5486 Header() +
5487 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5488 "; CHECK: [[float_8:%\\w+]] = OpConstant [[float]] 8\n" +
5489 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5490 "; CHECK: %4 = OpFDiv [[float]] [[float_8]] [[ld]]\n" +
5491 "%main = OpFunction %void None %void_func\n" +
5492 "%main_lab = OpLabel\n" +
5493 "%var = OpVariable %_ptr_float Function\n" +
5494 "%2 = OpLoad %float %var\n" +
5495 "%3 = OpFDiv %float %2 %float_2\n" +
5496 "%4 = OpFDiv %float %float_4 %3\n" +
5497 "OpReturn\n" +
5498 "OpFunctionEnd\n",
5499 4, true),
5500 // Test case 2: merge consecutive fdiv
5501 // (4.0 / x) / 2.0 = 2.0 / x
5502 InstructionFoldingCase<bool>(
5503 Header() +
5504 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5505 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5506 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5507 "; CHECK: %4 = OpFDiv [[float]] [[float_2]] [[ld]]\n" +
5508 "%main = OpFunction %void None %void_func\n" +
5509 "%main_lab = OpLabel\n" +
5510 "%var = OpVariable %_ptr_float Function\n" +
5511 "%2 = OpLoad %float %var\n" +
5512 "%3 = OpFDiv %float %float_4 %2\n" +
5513 "%4 = OpFDiv %float %3 %float_2\n" +
5514 "OpReturn\n" +
5515 "OpFunctionEnd\n",
5516 4, true),
5517 // Test case 3: Do not merge consecutive sdiv
5518 // 4 / (2 / x)
5519 InstructionFoldingCase<bool>(
5520 Header() +
5521 "%main = OpFunction %void None %void_func\n" +
5522 "%main_lab = OpLabel\n" +
5523 "%var = OpVariable %_ptr_int Function\n" +
5524 "%2 = OpLoad %int %var\n" +
5525 "%3 = OpSDiv %int %int_2 %2\n" +
5526 "%4 = OpSDiv %int %int_4 %3\n" +
5527 "OpReturn\n" +
5528 "OpFunctionEnd\n",
5529 4, false),
5530 // Test case 4: Do not merge consecutive sdiv
5531 // 4 / (x / 2)
5532 InstructionFoldingCase<bool>(
5533 Header() +
5534 "%main = OpFunction %void None %void_func\n" +
5535 "%main_lab = OpLabel\n" +
5536 "%var = OpVariable %_ptr_int Function\n" +
5537 "%2 = OpLoad %int %var\n" +
5538 "%3 = OpSDiv %int %2 %int_2\n" +
5539 "%4 = OpSDiv %int %int_4 %3\n" +
5540 "OpReturn\n" +
5541 "OpFunctionEnd\n",
5542 4, false),
5543 // Test case 5: Do not merge consecutive sdiv
5544 // (4 / x) / 2
5545 InstructionFoldingCase<bool>(
5546 Header() +
5547 "%main = OpFunction %void None %void_func\n" +
5548 "%main_lab = OpLabel\n" +
5549 "%var = OpVariable %_ptr_int Function\n" +
5550 "%2 = OpLoad %int %var\n" +
5551 "%3 = OpSDiv %int %int_4 %2\n" +
5552 "%4 = OpSDiv %int %3 %int_2\n" +
5553 "OpReturn\n" +
5554 "OpFunctionEnd\n",
5555 4, false),
5556 // Test case 6: Do not merge consecutive sdiv
5557 // (x / 4) / 2
5558 InstructionFoldingCase<bool>(
5559 Header() +
5560 "%main = OpFunction %void None %void_func\n" +
5561 "%main_lab = OpLabel\n" +
5562 "%var = OpVariable %_ptr_int Function\n" +
5563 "%2 = OpLoad %int %var\n" +
5564 "%3 = OpSDiv %int %2 %int_4\n" +
5565 "%4 = OpSDiv %int %3 %int_2\n" +
5566 "OpReturn\n" +
5567 "OpFunctionEnd\n",
5568 4, false),
5569 // Test case 7: Do not merge sdiv of imul
5570 // 4 / (2 * x)
5571 InstructionFoldingCase<bool>(
5572 Header() +
5573 "%main = OpFunction %void None %void_func\n" +
5574 "%main_lab = OpLabel\n" +
5575 "%var = OpVariable %_ptr_int Function\n" +
5576 "%2 = OpLoad %int %var\n" +
5577 "%3 = OpIMul %int %int_2 %2\n" +
5578 "%4 = OpSDiv %int %int_4 %3\n" +
5579 "OpReturn\n" +
5580 "OpFunctionEnd\n",
5581 4, false),
5582 // Test case 8: Do not merge sdiv of imul
5583 // 4 / (x * 2)
5584 InstructionFoldingCase<bool>(
5585 Header() +
5586 "%main = OpFunction %void None %void_func\n" +
5587 "%main_lab = OpLabel\n" +
5588 "%var = OpVariable %_ptr_int Function\n" +
5589 "%2 = OpLoad %int %var\n" +
5590 "%3 = OpIMul %int %2 %int_2\n" +
5591 "%4 = OpSDiv %int %int_4 %3\n" +
5592 "OpReturn\n" +
5593 "OpFunctionEnd\n",
5594 4, false),
5595 // Test case 9: Do not merge sdiv of imul
5596 // (4 * x) / 2
5597 InstructionFoldingCase<bool>(
5598 Header() +
5599 "%main = OpFunction %void None %void_func\n" +
5600 "%main_lab = OpLabel\n" +
5601 "%var = OpVariable %_ptr_int Function\n" +
5602 "%2 = OpLoad %int %var\n" +
5603 "%3 = OpIMul %int %int_4 %2\n" +
5604 "%4 = OpSDiv %int %3 %int_2\n" +
5605 "OpReturn\n" +
5606 "OpFunctionEnd\n",
5607 4, false),
5608 // Test case 10: Do not merge sdiv of imul
5609 // (x * 4) / 2
5610 InstructionFoldingCase<bool>(
5611 Header() +
5612 "%main = OpFunction %void None %void_func\n" +
5613 "%main_lab = OpLabel\n" +
5614 "%var = OpVariable %_ptr_int Function\n" +
5615 "%2 = OpLoad %int %var\n" +
5616 "%3 = OpIMul %int %2 %int_4\n" +
5617 "%4 = OpSDiv %int %3 %int_2\n" +
5618 "OpReturn\n" +
5619 "OpFunctionEnd\n",
5620 4, false),
5621 // Test case 11: merge sdiv of snegate
5622 // (-x) / 2 = x / -2
5623 InstructionFoldingCase<bool>(
5624 Header() +
5625 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5626 "; CHECK: OpConstant [[int]] -2147483648\n" +
5627 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
5628 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5629 "; CHECK: %4 = OpSDiv [[int]] [[ld]] [[int_n2]]\n" +
5630 "%main = OpFunction %void None %void_func\n" +
5631 "%main_lab = OpLabel\n" +
5632 "%var = OpVariable %_ptr_int Function\n" +
5633 "%2 = OpLoad %int %var\n" +
5634 "%3 = OpSNegate %int %2\n" +
5635 "%4 = OpSDiv %int %3 %int_2\n" +
5636 "OpReturn\n" +
5637 "OpFunctionEnd\n",
5638 4, true),
5639 // Test case 12: merge sdiv of snegate
5640 // 2 / (-x) = -2 / x
5641 InstructionFoldingCase<bool>(
5642 Header() +
5643 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5644 "; CHECK: OpConstant [[int]] -2147483648\n" +
5645 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
5646 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5647 "; CHECK: %4 = OpSDiv [[int]] [[int_n2]] [[ld]]\n" +
5648 "%main = OpFunction %void None %void_func\n" +
5649 "%main_lab = OpLabel\n" +
5650 "%var = OpVariable %_ptr_int Function\n" +
5651 "%2 = OpLoad %int %var\n" +
5652 "%3 = OpSNegate %int %2\n" +
5653 "%4 = OpSDiv %int %int_2 %3\n" +
5654 "OpReturn\n" +
5655 "OpFunctionEnd\n",
5656 4, true),
5657 // Test case 13: Don't merge
5658 // (x / {null}) / {null}
5659 InstructionFoldingCase<bool>(
5660 Header() +
5661 "%main = OpFunction %void None %void_func\n" +
5662 "%main_lab = OpLabel\n" +
5663 "%var = OpVariable %_ptr_v2float Function\n" +
5664 "%2 = OpLoad %float %var\n" +
5665 "%3 = OpFDiv %float %2 %v2float_null\n" +
5666 "%4 = OpFDiv %float %3 %v2float_null\n" +
5667 "OpReturn\n" +
5668 "OpFunctionEnd\n",
5669 4, false),
5670 // Test case 14: merge fmul of fdiv
5671 // (y * x) / x = y
5672 InstructionFoldingCase<bool>(
5673 Header() +
5674 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5675 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
5676 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
5677 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
5678 "%main = OpFunction %void None %void_func\n" +
5679 "%main_lab = OpLabel\n" +
5680 "%x = OpVariable %_ptr_float Function\n" +
5681 "%y = OpVariable %_ptr_float Function\n" +
5682 "%2 = OpLoad %float %x\n" +
5683 "%3 = OpLoad %float %y\n" +
5684 "%4 = OpFMul %float %3 %2\n" +
5685 "%5 = OpFDiv %float %4 %2\n" +
5686 "OpReturn\n" +
5687 "OpFunctionEnd\n",
5688 5, true),
5689 // Test case 15: merge fmul of fdiv
5690 // (x * y) / x = y
5691 InstructionFoldingCase<bool>(
5692 Header() +
5693 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5694 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
5695 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
5696 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
5697 "%main = OpFunction %void None %void_func\n" +
5698 "%main_lab = OpLabel\n" +
5699 "%x = OpVariable %_ptr_float Function\n" +
5700 "%y = OpVariable %_ptr_float Function\n" +
5701 "%2 = OpLoad %float %x\n" +
5702 "%3 = OpLoad %float %y\n" +
5703 "%4 = OpFMul %float %2 %3\n" +
5704 "%5 = OpFDiv %float %4 %2\n" +
5705 "OpReturn\n" +
5706 "OpFunctionEnd\n",
5707 5, true)
5708 ));
5709
5710 INSTANTIATE_TEST_SUITE_P(MergeAddTest, MatchingInstructionFoldingTest,
5711 ::testing::Values(
5712 // Test case 0: merge add of negate
5713 // (-x) + 2 = 2 - x
5714 InstructionFoldingCase<bool>(
5715 Header() +
5716 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5717 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5718 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5719 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
5720 "%main = OpFunction %void None %void_func\n" +
5721 "%main_lab = OpLabel\n" +
5722 "%var = OpVariable %_ptr_float Function\n" +
5723 "%2 = OpLoad %float %var\n" +
5724 "%3 = OpFNegate %float %2\n" +
5725 "%4 = OpFAdd %float %3 %float_2\n" +
5726 "OpReturn\n" +
5727 "OpFunctionEnd\n",
5728 4, true),
5729 // Test case 1: merge add of negate
5730 // 2 + (-x) = 2 - x
5731 InstructionFoldingCase<bool>(
5732 Header() +
5733 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5734 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5735 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5736 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
5737 "%main = OpFunction %void None %void_func\n" +
5738 "%main_lab = OpLabel\n" +
5739 "%var = OpVariable %_ptr_float Function\n" +
5740 "%2 = OpLoad %float %var\n" +
5741 "%3 = OpSNegate %float %2\n" +
5742 "%4 = OpIAdd %float %float_2 %3\n" +
5743 "OpReturn\n" +
5744 "OpFunctionEnd\n",
5745 4, true),
5746 // Test case 2: merge add of negate
5747 // (-x) + 2 = 2 - x
5748 InstructionFoldingCase<bool>(
5749 Header() +
5750 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5751 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5752 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5753 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
5754 "%main = OpFunction %void None %void_func\n" +
5755 "%main_lab = OpLabel\n" +
5756 "%var = OpVariable %_ptr_long Function\n" +
5757 "%2 = OpLoad %long %var\n" +
5758 "%3 = OpSNegate %long %2\n" +
5759 "%4 = OpIAdd %long %3 %long_2\n" +
5760 "OpReturn\n" +
5761 "OpFunctionEnd\n",
5762 4, true),
5763 // Test case 3: merge add of negate
5764 // 2 + (-x) = 2 - x
5765 InstructionFoldingCase<bool>(
5766 Header() +
5767 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5768 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5769 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5770 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
5771 "%main = OpFunction %void None %void_func\n" +
5772 "%main_lab = OpLabel\n" +
5773 "%var = OpVariable %_ptr_long Function\n" +
5774 "%2 = OpLoad %long %var\n" +
5775 "%3 = OpSNegate %long %2\n" +
5776 "%4 = OpIAdd %long %long_2 %3\n" +
5777 "OpReturn\n" +
5778 "OpFunctionEnd\n",
5779 4, true),
5780 // Test case 4: merge add of subtract
5781 // (x - 1) + 2 = x + 1
5782 InstructionFoldingCase<bool>(
5783 Header() +
5784 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5785 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
5786 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5787 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
5788 "%main = OpFunction %void None %void_func\n" +
5789 "%main_lab = OpLabel\n" +
5790 "%var = OpVariable %_ptr_float Function\n" +
5791 "%2 = OpLoad %float %var\n" +
5792 "%3 = OpFSub %float %2 %float_1\n" +
5793 "%4 = OpFAdd %float %3 %float_2\n" +
5794 "OpReturn\n" +
5795 "OpFunctionEnd\n",
5796 4, true),
5797 // Test case 5: merge add of subtract
5798 // (1 - x) + 2 = 3 - x
5799 InstructionFoldingCase<bool>(
5800 Header() +
5801 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5802 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5803 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5804 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
5805 "%main = OpFunction %void None %void_func\n" +
5806 "%main_lab = OpLabel\n" +
5807 "%var = OpVariable %_ptr_float Function\n" +
5808 "%2 = OpLoad %float %var\n" +
5809 "%3 = OpFSub %float %float_1 %2\n" +
5810 "%4 = OpFAdd %float %3 %float_2\n" +
5811 "OpReturn\n" +
5812 "OpFunctionEnd\n",
5813 4, true),
5814 // Test case 6: merge add of subtract
5815 // 2 + (x - 1) = x + 1
5816 InstructionFoldingCase<bool>(
5817 Header() +
5818 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5819 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
5820 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5821 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
5822 "%main = OpFunction %void None %void_func\n" +
5823 "%main_lab = OpLabel\n" +
5824 "%var = OpVariable %_ptr_float Function\n" +
5825 "%2 = OpLoad %float %var\n" +
5826 "%3 = OpFSub %float %2 %float_1\n" +
5827 "%4 = OpFAdd %float %float_2 %3\n" +
5828 "OpReturn\n" +
5829 "OpFunctionEnd\n",
5830 4, true),
5831 // Test case 7: merge add of subtract
5832 // 2 + (1 - x) = 3 - x
5833 InstructionFoldingCase<bool>(
5834 Header() +
5835 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5836 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5837 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5838 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
5839 "%main = OpFunction %void None %void_func\n" +
5840 "%main_lab = OpLabel\n" +
5841 "%var = OpVariable %_ptr_float Function\n" +
5842 "%2 = OpLoad %float %var\n" +
5843 "%3 = OpFSub %float %float_1 %2\n" +
5844 "%4 = OpFAdd %float %float_2 %3\n" +
5845 "OpReturn\n" +
5846 "OpFunctionEnd\n",
5847 4, true),
5848 // Test case 8: merge add of add
5849 // (x + 1) + 2 = x + 3
5850 InstructionFoldingCase<bool>(
5851 Header() +
5852 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5853 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5854 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5855 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
5856 "%main = OpFunction %void None %void_func\n" +
5857 "%main_lab = OpLabel\n" +
5858 "%var = OpVariable %_ptr_float Function\n" +
5859 "%2 = OpLoad %float %var\n" +
5860 "%3 = OpFAdd %float %2 %float_1\n" +
5861 "%4 = OpFAdd %float %3 %float_2\n" +
5862 "OpReturn\n" +
5863 "OpFunctionEnd\n",
5864 4, true),
5865 // Test case 9: merge add of add
5866 // (1 + x) + 2 = 3 + x
5867 InstructionFoldingCase<bool>(
5868 Header() +
5869 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5870 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5871 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5872 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
5873 "%main = OpFunction %void None %void_func\n" +
5874 "%main_lab = OpLabel\n" +
5875 "%var = OpVariable %_ptr_float Function\n" +
5876 "%2 = OpLoad %float %var\n" +
5877 "%3 = OpFAdd %float %float_1 %2\n" +
5878 "%4 = OpFAdd %float %3 %float_2\n" +
5879 "OpReturn\n" +
5880 "OpFunctionEnd\n",
5881 4, true),
5882 // Test case 10: merge add of add
5883 // 2 + (x + 1) = x + 1
5884 InstructionFoldingCase<bool>(
5885 Header() +
5886 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5887 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5888 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5889 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
5890 "%main = OpFunction %void None %void_func\n" +
5891 "%main_lab = OpLabel\n" +
5892 "%var = OpVariable %_ptr_float Function\n" +
5893 "%2 = OpLoad %float %var\n" +
5894 "%3 = OpFAdd %float %2 %float_1\n" +
5895 "%4 = OpFAdd %float %float_2 %3\n" +
5896 "OpReturn\n" +
5897 "OpFunctionEnd\n",
5898 4, true),
5899 // Test case 11: merge add of add
5900 // 2 + (1 + x) = 3 - x
5901 InstructionFoldingCase<bool>(
5902 Header() +
5903 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5904 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
5905 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5906 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
5907 "%main = OpFunction %void None %void_func\n" +
5908 "%main_lab = OpLabel\n" +
5909 "%var = OpVariable %_ptr_float Function\n" +
5910 "%2 = OpLoad %float %var\n" +
5911 "%3 = OpFAdd %float %float_1 %2\n" +
5912 "%4 = OpFAdd %float %float_2 %3\n" +
5913 "OpReturn\n" +
5914 "OpFunctionEnd\n",
5915 4, true)
5916 ));
5917
5918 INSTANTIATE_TEST_SUITE_P(MergeGenericAddSub, MatchingInstructionFoldingTest,
5919 ::testing::Values(
5920 // Test case 0: merge of add of sub
5921 // (a - b) + b => a
5922 InstructionFoldingCase<bool>(
5923 Header() +
5924 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5925 "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
5926 "%main = OpFunction %void None %void_func\n" +
5927 "%main_lab = OpLabel\n" +
5928 "%var0 = OpVariable %_ptr_float Function\n" +
5929 "%var1 = OpVariable %_ptr_float Function\n" +
5930 "%3 = OpLoad %float %var0\n" +
5931 "%4 = OpLoad %float %var1\n" +
5932 "%5 = OpFSub %float %3 %4\n" +
5933 "%6 = OpFAdd %float %5 %4\n" +
5934 "OpReturn\n" +
5935 "OpFunctionEnd\n",
5936 6, true),
5937 // Test case 1: merge of add of sub
5938 // b + (a - b) => a
5939 InstructionFoldingCase<bool>(
5940 Header() +
5941 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5942 "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
5943 "%main = OpFunction %void None %void_func\n" +
5944 "%main_lab = OpLabel\n" +
5945 "%var0 = OpVariable %_ptr_float Function\n" +
5946 "%var1 = OpVariable %_ptr_float Function\n" +
5947 "%3 = OpLoad %float %var0\n" +
5948 "%4 = OpLoad %float %var1\n" +
5949 "%5 = OpFSub %float %3 %4\n" +
5950 "%6 = OpFAdd %float %4 %5\n" +
5951 "OpReturn\n" +
5952 "OpFunctionEnd\n",
5953 6, true)
5954 ));
5955
5956 INSTANTIATE_TEST_SUITE_P(FactorAddMul, MatchingInstructionFoldingTest,
5957 ::testing::Values(
5958 // Test case 0: factor of add of muls
5959 // (a * b) + (a * c) => a * (b + c)
5960 InstructionFoldingCase<bool>(
5961 Header() +
5962 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5963 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
5964 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
5965 "%main = OpFunction %void None %void_func\n" +
5966 "%main_lab = OpLabel\n" +
5967 "%var0 = OpVariable %_ptr_float Function\n" +
5968 "%var1 = OpVariable %_ptr_float Function\n" +
5969 "%var2 = OpVariable %_ptr_float Function\n" +
5970 "%4 = OpLoad %float %var0\n" +
5971 "%5 = OpLoad %float %var1\n" +
5972 "%6 = OpLoad %float %var2\n" +
5973 "%7 = OpFMul %float %6 %4\n" +
5974 "%8 = OpFMul %float %6 %5\n" +
5975 "%9 = OpFAdd %float %7 %8\n" +
5976 "OpReturn\n" +
5977 "OpFunctionEnd\n",
5978 9, true),
5979 // Test case 1: factor of add of muls
5980 // (b * a) + (a * c) => a * (b + c)
5981 InstructionFoldingCase<bool>(
5982 Header() +
5983 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5984 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
5985 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
5986 "%main = OpFunction %void None %void_func\n" +
5987 "%main_lab = OpLabel\n" +
5988 "%var0 = OpVariable %_ptr_float Function\n" +
5989 "%var1 = OpVariable %_ptr_float Function\n" +
5990 "%var2 = OpVariable %_ptr_float Function\n" +
5991 "%4 = OpLoad %float %var0\n" +
5992 "%5 = OpLoad %float %var1\n" +
5993 "%6 = OpLoad %float %var2\n" +
5994 "%7 = OpFMul %float %4 %6\n" +
5995 "%8 = OpFMul %float %6 %5\n" +
5996 "%9 = OpFAdd %float %7 %8\n" +
5997 "OpReturn\n" +
5998 "OpFunctionEnd\n",
5999 9, true),
6000 // Test case 2: factor of add of muls
6001 // (a * b) + (c * a) => a * (b + c)
6002 InstructionFoldingCase<bool>(
6003 Header() +
6004 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6005 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
6006 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
6007 "%main = OpFunction %void None %void_func\n" +
6008 "%main_lab = OpLabel\n" +
6009 "%var0 = OpVariable %_ptr_float Function\n" +
6010 "%var1 = OpVariable %_ptr_float Function\n" +
6011 "%var2 = OpVariable %_ptr_float Function\n" +
6012 "%4 = OpLoad %float %var0\n" +
6013 "%5 = OpLoad %float %var1\n" +
6014 "%6 = OpLoad %float %var2\n" +
6015 "%7 = OpFMul %float %6 %4\n" +
6016 "%8 = OpFMul %float %5 %6\n" +
6017 "%9 = OpFAdd %float %7 %8\n" +
6018 "OpReturn\n" +
6019 "OpFunctionEnd\n",
6020 9, true),
6021 // Test case 3: factor of add of muls
6022 // (b * a) + (c * a) => a * (b + c)
6023 InstructionFoldingCase<bool>(
6024 Header() +
6025 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6026 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
6027 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
6028 "%main = OpFunction %void None %void_func\n" +
6029 "%main_lab = OpLabel\n" +
6030 "%var0 = OpVariable %_ptr_float Function\n" +
6031 "%var1 = OpVariable %_ptr_float Function\n" +
6032 "%var2 = OpVariable %_ptr_float Function\n" +
6033 "%4 = OpLoad %float %var0\n" +
6034 "%5 = OpLoad %float %var1\n" +
6035 "%6 = OpLoad %float %var2\n" +
6036 "%7 = OpFMul %float %4 %6\n" +
6037 "%8 = OpFMul %float %5 %6\n" +
6038 "%9 = OpFAdd %float %7 %8\n" +
6039 "OpReturn\n" +
6040 "OpFunctionEnd\n",
6041 9, true)
6042 ));
6043
6044 INSTANTIATE_TEST_SUITE_P(MergeSubTest, MatchingInstructionFoldingTest,
6045 ::testing::Values(
6046 // Test case 0: merge sub of negate
6047 // (-x) - 2 = -2 - x
6048 InstructionFoldingCase<bool>(
6049 Header() +
6050 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6051 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
6052 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6053 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
6054 "%main = OpFunction %void None %void_func\n" +
6055 "%main_lab = OpLabel\n" +
6056 "%var = OpVariable %_ptr_float Function\n" +
6057 "%2 = OpLoad %float %var\n" +
6058 "%3 = OpFNegate %float %2\n" +
6059 "%4 = OpFSub %float %3 %float_2\n" +
6060 "OpReturn\n" +
6061 "OpFunctionEnd\n",
6062 4, true),
6063 // Test case 1: merge sub of negate
6064 // 2 - (-x) = x + 2
6065 InstructionFoldingCase<bool>(
6066 Header() +
6067 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6068 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6069 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6070 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_2]]\n" +
6071 "%main = OpFunction %void None %void_func\n" +
6072 "%main_lab = OpLabel\n" +
6073 "%var = OpVariable %_ptr_float Function\n" +
6074 "%2 = OpLoad %float %var\n" +
6075 "%3 = OpFNegate %float %2\n" +
6076 "%4 = OpFSub %float %float_2 %3\n" +
6077 "OpReturn\n" +
6078 "OpFunctionEnd\n",
6079 4, true),
6080 // Test case 2: merge sub of negate
6081 // (-x) - 2 = -2 - x
6082 InstructionFoldingCase<bool>(
6083 Header() +
6084 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
6085 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
6086 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6087 "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
6088 "%main = OpFunction %void None %void_func\n" +
6089 "%main_lab = OpLabel\n" +
6090 "%var = OpVariable %_ptr_long Function\n" +
6091 "%2 = OpLoad %long %var\n" +
6092 "%3 = OpSNegate %long %2\n" +
6093 "%4 = OpISub %long %3 %long_2\n" +
6094 "OpReturn\n" +
6095 "OpFunctionEnd\n",
6096 4, true),
6097 // Test case 3: merge sub of negate
6098 // 2 - (-x) = x + 2
6099 InstructionFoldingCase<bool>(
6100 Header() +
6101 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
6102 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
6103 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6104 "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_2]]\n" +
6105 "%main = OpFunction %void None %void_func\n" +
6106 "%main_lab = OpLabel\n" +
6107 "%var = OpVariable %_ptr_long Function\n" +
6108 "%2 = OpLoad %long %var\n" +
6109 "%3 = OpSNegate %long %2\n" +
6110 "%4 = OpISub %long %long_2 %3\n" +
6111 "OpReturn\n" +
6112 "OpFunctionEnd\n",
6113 4, true),
6114 // Test case 4: merge add of subtract
6115 // (x + 2) - 1 = x + 1
6116 InstructionFoldingCase<bool>(
6117 Header() +
6118 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6119 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
6120 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6121 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
6122 "%main = OpFunction %void None %void_func\n" +
6123 "%main_lab = OpLabel\n" +
6124 "%var = OpVariable %_ptr_float Function\n" +
6125 "%2 = OpLoad %float %var\n" +
6126 "%3 = OpFAdd %float %2 %float_2\n" +
6127 "%4 = OpFSub %float %3 %float_1\n" +
6128 "OpReturn\n" +
6129 "OpFunctionEnd\n",
6130 4, true),
6131 // Test case 5: merge add of subtract
6132 // (2 + x) - 1 = x + 1
6133 InstructionFoldingCase<bool>(
6134 Header() +
6135 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6136 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
6137 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6138 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
6139 "%main = OpFunction %void None %void_func\n" +
6140 "%main_lab = OpLabel\n" +
6141 "%var = OpVariable %_ptr_float Function\n" +
6142 "%2 = OpLoad %float %var\n" +
6143 "%3 = OpFAdd %float %float_2 %2\n" +
6144 "%4 = OpFSub %float %3 %float_1\n" +
6145 "OpReturn\n" +
6146 "OpFunctionEnd\n",
6147 4, true),
6148 // Test case 6: merge add of subtract
6149 // 2 - (x + 1) = 1 - x
6150 InstructionFoldingCase<bool>(
6151 Header() +
6152 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6153 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
6154 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6155 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
6156 "%main = OpFunction %void None %void_func\n" +
6157 "%main_lab = OpLabel\n" +
6158 "%var = OpVariable %_ptr_float Function\n" +
6159 "%2 = OpLoad %float %var\n" +
6160 "%3 = OpFAdd %float %2 %float_1\n" +
6161 "%4 = OpFSub %float %float_2 %3\n" +
6162 "OpReturn\n" +
6163 "OpFunctionEnd\n",
6164 4, true),
6165 // Test case 7: merge add of subtract
6166 // 2 - (1 + x) = 1 - x
6167 InstructionFoldingCase<bool>(
6168 Header() +
6169 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6170 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
6171 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6172 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
6173 "%main = OpFunction %void None %void_func\n" +
6174 "%main_lab = OpLabel\n" +
6175 "%var = OpVariable %_ptr_float Function\n" +
6176 "%2 = OpLoad %float %var\n" +
6177 "%3 = OpFAdd %float %float_1 %2\n" +
6178 "%4 = OpFSub %float %float_2 %3\n" +
6179 "OpReturn\n" +
6180 "OpFunctionEnd\n",
6181 4, true),
6182 // Test case 8: merge subtract of subtract
6183 // (x - 2) - 1 = x - 3
6184 InstructionFoldingCase<bool>(
6185 Header() +
6186 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6187 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6188 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6189 "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_3]]\n" +
6190 "%main = OpFunction %void None %void_func\n" +
6191 "%main_lab = OpLabel\n" +
6192 "%var = OpVariable %_ptr_float Function\n" +
6193 "%2 = OpLoad %float %var\n" +
6194 "%3 = OpFSub %float %2 %float_2\n" +
6195 "%4 = OpFSub %float %3 %float_1\n" +
6196 "OpReturn\n" +
6197 "OpFunctionEnd\n",
6198 4, true),
6199 // Test case 9: merge subtract of subtract
6200 // (2 - x) - 1 = 1 - x
6201 InstructionFoldingCase<bool>(
6202 Header() +
6203 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6204 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
6205 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6206 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
6207 "%main = OpFunction %void None %void_func\n" +
6208 "%main_lab = OpLabel\n" +
6209 "%var = OpVariable %_ptr_float Function\n" +
6210 "%2 = OpLoad %float %var\n" +
6211 "%3 = OpFSub %float %float_2 %2\n" +
6212 "%4 = OpFSub %float %3 %float_1\n" +
6213 "OpReturn\n" +
6214 "OpFunctionEnd\n",
6215 4, true),
6216 // Test case 10: merge subtract of subtract
6217 // 2 - (x - 1) = 3 - x
6218 InstructionFoldingCase<bool>(
6219 Header() +
6220 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6221 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
6222 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6223 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
6224 "%main = OpFunction %void None %void_func\n" +
6225 "%main_lab = OpLabel\n" +
6226 "%var = OpVariable %_ptr_float Function\n" +
6227 "%2 = OpLoad %float %var\n" +
6228 "%3 = OpFSub %float %2 %float_1\n" +
6229 "%4 = OpFSub %float %float_2 %3\n" +
6230 "OpReturn\n" +
6231 "OpFunctionEnd\n",
6232 4, true),
6233 // Test case 11: merge subtract of subtract
6234 // 1 - (2 - x) = x + (-1)
6235 InstructionFoldingCase<bool>(
6236 Header() +
6237 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6238 "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
6239 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6240 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_n1]]\n" +
6241 "%main = OpFunction %void None %void_func\n" +
6242 "%main_lab = OpLabel\n" +
6243 "%var = OpVariable %_ptr_float Function\n" +
6244 "%2 = OpLoad %float %var\n" +
6245 "%3 = OpFSub %float %float_2 %2\n" +
6246 "%4 = OpFSub %float %float_1 %3\n" +
6247 "OpReturn\n" +
6248 "OpFunctionEnd\n",
6249 4, true),
6250 // Test case 12: merge subtract of subtract
6251 // 2 - (1 - x) = x + 1
6252 InstructionFoldingCase<bool>(
6253 Header() +
6254 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6255 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
6256 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6257 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
6258 "%main = OpFunction %void None %void_func\n" +
6259 "%main_lab = OpLabel\n" +
6260 "%var = OpVariable %_ptr_float Function\n" +
6261 "%2 = OpLoad %float %var\n" +
6262 "%3 = OpFSub %float %float_1 %2\n" +
6263 "%4 = OpFSub %float %float_2 %3\n" +
6264 "OpReturn\n" +
6265 "OpFunctionEnd\n",
6266 4, true),
6267 // Test case 13: merge subtract of subtract with mixed types.
6268 // 2 - (1 - x) = x + 1
6269 InstructionFoldingCase<bool>(
6270 Header() +
6271 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6272 "; CHECK: [[int_1:%\\w+]] = OpConstant [[int]] 1\n" +
6273 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6274 "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_1]]\n" +
6275 "%main = OpFunction %void None %void_func\n" +
6276 "%main_lab = OpLabel\n" +
6277 "%var = OpVariable %_ptr_int Function\n" +
6278 "%2 = OpLoad %int %var\n" +
6279 "%3 = OpISub %int %uint_1 %2\n" +
6280 "%4 = OpISub %int %int_2 %3\n" +
6281 "OpReturn\n" +
6282 "OpFunctionEnd\n",
6283 4, true)
6284 ));
6285
6286 INSTANTIATE_TEST_SUITE_P(SelectFoldingTest, MatchingInstructionFoldingTest,
6287 ::testing::Values(
6288 // Test case 0: Fold select with the same values for both sides
6289 InstructionFoldingCase<bool>(
6290 Header() +
6291 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6292 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
6293 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
6294 "%main = OpFunction %void None %void_func\n" +
6295 "%main_lab = OpLabel\n" +
6296 "%n = OpVariable %_ptr_bool Function\n" +
6297 "%load = OpLoad %bool %n\n" +
6298 "%2 = OpSelect %int %load %100 %100\n" +
6299 "OpReturn\n" +
6300 "OpFunctionEnd",
6301 2, true),
6302 // Test case 1: Fold select true to left side
6303 InstructionFoldingCase<bool>(
6304 Header() +
6305 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6306 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
6307 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
6308 "%main = OpFunction %void None %void_func\n" +
6309 "%main_lab = OpLabel\n" +
6310 "%n = OpVariable %_ptr_int Function\n" +
6311 "%load = OpLoad %bool %n\n" +
6312 "%2 = OpSelect %int %true %100 %n\n" +
6313 "OpReturn\n" +
6314 "OpFunctionEnd",
6315 2, true),
6316 // Test case 2: Fold select false to right side
6317 InstructionFoldingCase<bool>(
6318 Header() +
6319 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6320 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
6321 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
6322 "%main = OpFunction %void None %void_func\n" +
6323 "%main_lab = OpLabel\n" +
6324 "%n = OpVariable %_ptr_int Function\n" +
6325 "%load = OpLoad %bool %n\n" +
6326 "%2 = OpSelect %int %false %n %100\n" +
6327 "OpReturn\n" +
6328 "OpFunctionEnd",
6329 2, true),
6330 // Test case 3: Fold select null to right side
6331 InstructionFoldingCase<bool>(
6332 Header() +
6333 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6334 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
6335 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
6336 "%main = OpFunction %void None %void_func\n" +
6337 "%main_lab = OpLabel\n" +
6338 "%n = OpVariable %_ptr_int Function\n" +
6339 "%load = OpLoad %int %n\n" +
6340 "%2 = OpSelect %int %bool_null %load %100\n" +
6341 "OpReturn\n" +
6342 "OpFunctionEnd",
6343 2, true),
6344 // Test case 4: vector null
6345 InstructionFoldingCase<bool>(
6346 Header() +
6347 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6348 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
6349 "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
6350 "; CHECK: [[v2int2_2:%\\w+]] = OpConstantComposite [[v2int]] [[int2]] [[int2]]\n" +
6351 "; CHECK: %2 = OpCopyObject [[v2int]] [[v2int2_2]]\n" +
6352 "%main = OpFunction %void None %void_func\n" +
6353 "%main_lab = OpLabel\n" +
6354 "%n = OpVariable %_ptr_v2int Function\n" +
6355 "%load = OpLoad %v2int %n\n" +
6356 "%2 = OpSelect %v2int %v2bool_null %load %v2int_2_2\n" +
6357 "OpReturn\n" +
6358 "OpFunctionEnd",
6359 2, true),
6360 // Test case 5: vector select
6361 InstructionFoldingCase<bool>(
6362 Header() +
6363 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6364 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
6365 "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 0 3\n" +
6366 "%main = OpFunction %void None %void_func\n" +
6367 "%main_lab = OpLabel\n" +
6368 "%m = OpVariable %_ptr_v2int Function\n" +
6369 "%n = OpVariable %_ptr_v2int Function\n" +
6370 "%2 = OpLoad %v2int %n\n" +
6371 "%3 = OpLoad %v2int %n\n" +
6372 "%4 = OpSelect %v2int %v2bool_true_false %2 %3\n" +
6373 "OpReturn\n" +
6374 "OpFunctionEnd",
6375 4, true),
6376 // Test case 6: vector select
6377 InstructionFoldingCase<bool>(
6378 Header() +
6379 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6380 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
6381 "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 2 1\n" +
6382 "%main = OpFunction %void None %void_func\n" +
6383 "%main_lab = OpLabel\n" +
6384 "%m = OpVariable %_ptr_v2int Function\n" +
6385 "%n = OpVariable %_ptr_v2int Function\n" +
6386 "%2 = OpLoad %v2int %n\n" +
6387 "%3 = OpLoad %v2int %n\n" +
6388 "%4 = OpSelect %v2int %v2bool_false_true %2 %3\n" +
6389 "OpReturn\n" +
6390 "OpFunctionEnd",
6391 4, true)
6392 ));
6393
6394 INSTANTIATE_TEST_SUITE_P(CompositeExtractMatchingTest, MatchingInstructionFoldingTest,
6395 ::testing::Values(
6396 // Test case 0: Extracting from result of consecutive shuffles of differing
6397 // size.
6398 InstructionFoldingCase<bool>(
6399 Header() +
6400 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6401 "; CHECK: %5 = OpCompositeExtract [[int]] %2 2\n" +
6402 "%main = OpFunction %void None %void_func\n" +
6403 "%main_lab = OpLabel\n" +
6404 "%n = OpVariable %_ptr_v4int Function\n" +
6405 "%2 = OpLoad %v4int %n\n" +
6406 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
6407 "%4 = OpVectorShuffle %v4int %2 %3 0 4 2 5\n" +
6408 "%5 = OpCompositeExtract %int %4 1\n" +
6409 "OpReturn\n" +
6410 "OpFunctionEnd",
6411 5, true),
6412 // Test case 1: Extracting from result of vector shuffle of differing
6413 // input and result sizes.
6414 InstructionFoldingCase<bool>(
6415 Header() +
6416 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6417 "; CHECK: %4 = OpCompositeExtract [[int]] %2 2\n" +
6418 "%main = OpFunction %void None %void_func\n" +
6419 "%main_lab = OpLabel\n" +
6420 "%n = OpVariable %_ptr_v4int Function\n" +
6421 "%2 = OpLoad %v4int %n\n" +
6422 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
6423 "%4 = OpCompositeExtract %int %3 0\n" +
6424 "OpReturn\n" +
6425 "OpFunctionEnd",
6426 4, true),
6427 // Test case 2: Extracting from result of vector shuffle of differing
6428 // input and result sizes.
6429 InstructionFoldingCase<bool>(
6430 Header() +
6431 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6432 "; CHECK: %4 = OpCompositeExtract [[int]] %2 3\n" +
6433 "%main = OpFunction %void None %void_func\n" +
6434 "%main_lab = OpLabel\n" +
6435 "%n = OpVariable %_ptr_v4int Function\n" +
6436 "%2 = OpLoad %v4int %n\n" +
6437 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
6438 "%4 = OpCompositeExtract %int %3 1\n" +
6439 "OpReturn\n" +
6440 "OpFunctionEnd",
6441 4, true),
6442 // Test case 3: Using fmix feeding extract with a 1 in the a position.
6443 InstructionFoldingCase<bool>(
6444 Header() +
6445 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6446 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
6447 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
6448 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
6449 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
6450 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[n]]\n" +
6451 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 1\n" +
6452 "%main = OpFunction %void None %void_func\n" +
6453 "%main_lab = OpLabel\n" +
6454 "%m = OpVariable %_ptr_v4double Function\n" +
6455 "%n = OpVariable %_ptr_v4double Function\n" +
6456 "%2 = OpLoad %v4double %m\n" +
6457 "%3 = OpLoad %v4double %n\n" +
6458 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
6459 "%5 = OpCompositeExtract %double %4 1\n" +
6460 "OpReturn\n" +
6461 "OpFunctionEnd",
6462 5, true),
6463 // Test case 4: Using fmix feeding extract with a 0 in the a position.
6464 InstructionFoldingCase<bool>(
6465 Header() +
6466 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6467 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
6468 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
6469 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
6470 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
6471 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
6472 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 2\n" +
6473 "%main = OpFunction %void None %void_func\n" +
6474 "%main_lab = OpLabel\n" +
6475 "%m = OpVariable %_ptr_v4double Function\n" +
6476 "%n = OpVariable %_ptr_v4double Function\n" +
6477 "%2 = OpLoad %v4double %m\n" +
6478 "%3 = OpLoad %v4double %n\n" +
6479 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
6480 "%5 = OpCompositeExtract %double %4 2\n" +
6481 "OpReturn\n" +
6482 "OpFunctionEnd",
6483 5, true),
6484 // Test case 5: Using fmix feeding extract with a null for the alpha
6485 InstructionFoldingCase<bool>(
6486 Header() +
6487 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6488 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
6489 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
6490 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
6491 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
6492 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
6493 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 0\n" +
6494 "%main = OpFunction %void None %void_func\n" +
6495 "%main_lab = OpLabel\n" +
6496 "%m = OpVariable %_ptr_v4double Function\n" +
6497 "%n = OpVariable %_ptr_v4double Function\n" +
6498 "%2 = OpLoad %v4double %m\n" +
6499 "%3 = OpLoad %v4double %n\n" +
6500 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_null\n" +
6501 "%5 = OpCompositeExtract %double %4 0\n" +
6502 "OpReturn\n" +
6503 "OpFunctionEnd",
6504 5, true),
6505 // Test case 6: Don't fold: Using fmix feeding extract with 0.5 in the a
6506 // position.
6507 InstructionFoldingCase<bool>(
6508 Header() +
6509 "%main = OpFunction %void None %void_func\n" +
6510 "%main_lab = OpLabel\n" +
6511 "%m = OpVariable %_ptr_v4double Function\n" +
6512 "%n = OpVariable %_ptr_v4double Function\n" +
6513 "%2 = OpLoad %v4double %m\n" +
6514 "%3 = OpLoad %v4double %n\n" +
6515 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_1_1_1_0p5\n" +
6516 "%5 = OpCompositeExtract %double %4 3\n" +
6517 "OpReturn\n" +
6518 "OpFunctionEnd",
6519 5, false),
6520 // Test case 7: Extracting the undefined literal value from a vector
6521 // shuffle.
6522 InstructionFoldingCase<bool>(
6523 Header() +
6524 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6525 "; CHECK: %4 = OpUndef [[int]]\n" +
6526 "%main = OpFunction %void None %void_func\n" +
6527 "%main_lab = OpLabel\n" +
6528 "%n = OpVariable %_ptr_v4int Function\n" +
6529 "%2 = OpLoad %v4int %n\n" +
6530 "%3 = OpVectorShuffle %v2int %2 %2 2 4294967295\n" +
6531 "%4 = OpCompositeExtract %int %3 1\n" +
6532 "OpReturn\n" +
6533 "OpFunctionEnd",
6534 4, true)
6535 ));
6536
6537 INSTANTIATE_TEST_SUITE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
6538 ::testing::Values(
6539 // Test case 0: Using OpDot to extract last element.
6540 InstructionFoldingCase<bool>(
6541 Header() +
6542 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6543 "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
6544 "%main = OpFunction %void None %void_func\n" +
6545 "%main_lab = OpLabel\n" +
6546 "%n = OpVariable %_ptr_v4float Function\n" +
6547 "%2 = OpLoad %v4float %n\n" +
6548 "%3 = OpDot %float %2 %v4float_0_0_0_1\n" +
6549 "OpReturn\n" +
6550 "OpFunctionEnd",
6551 3, true),
6552 // Test case 1: Using OpDot to extract last element.
6553 InstructionFoldingCase<bool>(
6554 Header() +
6555 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6556 "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
6557 "%main = OpFunction %void None %void_func\n" +
6558 "%main_lab = OpLabel\n" +
6559 "%n = OpVariable %_ptr_v4float Function\n" +
6560 "%2 = OpLoad %v4float %n\n" +
6561 "%3 = OpDot %float %v4float_0_0_0_1 %2\n" +
6562 "OpReturn\n" +
6563 "OpFunctionEnd",
6564 3, true),
6565 // Test case 2: Using OpDot to extract second element.
6566 InstructionFoldingCase<bool>(
6567 Header() +
6568 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6569 "; CHECK: %3 = OpCompositeExtract [[float]] %2 1\n" +
6570 "%main = OpFunction %void None %void_func\n" +
6571 "%main_lab = OpLabel\n" +
6572 "%n = OpVariable %_ptr_v4float Function\n" +
6573 "%2 = OpLoad %v4float %n\n" +
6574 "%3 = OpDot %float %v4float_0_1_0_0 %2\n" +
6575 "OpReturn\n" +
6576 "OpFunctionEnd",
6577 3, true),
6578 // Test case 3: Using OpDot to extract last element.
6579 InstructionFoldingCase<bool>(
6580 Header() +
6581 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6582 "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
6583 "%main = OpFunction %void None %void_func\n" +
6584 "%main_lab = OpLabel\n" +
6585 "%n = OpVariable %_ptr_v4double Function\n" +
6586 "%2 = OpLoad %v4double %n\n" +
6587 "%3 = OpDot %double %2 %v4double_0_0_0_1\n" +
6588 "OpReturn\n" +
6589 "OpFunctionEnd",
6590 3, true),
6591 // Test case 4: Using OpDot to extract last element.
6592 InstructionFoldingCase<bool>(
6593 Header() +
6594 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6595 "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
6596 "%main = OpFunction %void None %void_func\n" +
6597 "%main_lab = OpLabel\n" +
6598 "%n = OpVariable %_ptr_v4double Function\n" +
6599 "%2 = OpLoad %v4double %n\n" +
6600 "%3 = OpDot %double %v4double_0_0_0_1 %2\n" +
6601 "OpReturn\n" +
6602 "OpFunctionEnd",
6603 3, true),
6604 // Test case 5: Using OpDot to extract second element.
6605 InstructionFoldingCase<bool>(
6606 Header() +
6607 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6608 "; CHECK: %3 = OpCompositeExtract [[double]] %2 1\n" +
6609 "%main = OpFunction %void None %void_func\n" +
6610 "%main_lab = OpLabel\n" +
6611 "%n = OpVariable %_ptr_v4double Function\n" +
6612 "%2 = OpLoad %v4double %n\n" +
6613 "%3 = OpDot %double %v4double_0_1_0_0 %2\n" +
6614 "OpReturn\n" +
6615 "OpFunctionEnd",
6616 3, true)
6617 ));
6618
6619 using MatchingInstructionWithNoResultFoldingTest =
6620 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
6621
6622 // Test folding instructions that do not have a result. The instruction
6623 // that will be folded is the last instruction before the return. If there
6624 // are multiple returns, there is not guarentee which one is used.
TEST_P(MatchingInstructionWithNoResultFoldingTest,Case)6625 TEST_P(MatchingInstructionWithNoResultFoldingTest, Case) {
6626 const auto& tc = GetParam();
6627
6628 // Build module.
6629 std::unique_ptr<IRContext> context =
6630 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
6631 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6632 ASSERT_NE(nullptr, context);
6633
6634 // Fold the instruction to test.
6635 Instruction* inst = nullptr;
6636 Function* func = &*context->module()->begin();
6637 for (auto& bb : *func) {
6638 Instruction* terminator = bb.terminator();
6639 if (terminator->IsReturnOrAbort()) {
6640 inst = terminator->PreviousNode();
6641 break;
6642 }
6643 }
6644 assert(inst && "Invalid test. Could not find instruction to fold.");
6645 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
6646 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
6647 EXPECT_EQ(succeeded, tc.expected_result);
6648 if (succeeded) {
6649 Match(tc.test_body, context.get());
6650 }
6651 }
6652
6653 INSTANTIATE_TEST_SUITE_P(StoreMatchingTest, MatchingInstructionWithNoResultFoldingTest,
6654 ::testing::Values(
6655 // Test case 0: Remove store of undef.
6656 InstructionFoldingCase<bool>(
6657 Header() +
6658 "; CHECK: OpLabel\n" +
6659 "; CHECK-NOT: OpStore\n" +
6660 "; CHECK: OpReturn\n" +
6661 "%main = OpFunction %void None %void_func\n" +
6662 "%main_lab = OpLabel\n" +
6663 "%n = OpVariable %_ptr_v4double Function\n" +
6664 "%undef = OpUndef %v4double\n" +
6665 "OpStore %n %undef\n" +
6666 "OpReturn\n" +
6667 "OpFunctionEnd",
6668 0 /* OpStore */, true),
6669 // Test case 1: Keep volatile store.
6670 InstructionFoldingCase<bool>(
6671 Header() +
6672 "%main = OpFunction %void None %void_func\n" +
6673 "%main_lab = OpLabel\n" +
6674 "%n = OpVariable %_ptr_v4double Function\n" +
6675 "%undef = OpUndef %v4double\n" +
6676 "OpStore %n %undef Volatile\n" +
6677 "OpReturn\n" +
6678 "OpFunctionEnd",
6679 0 /* OpStore */, false)
6680 ));
6681
6682 INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoResultFoldingTest,
6683 ::testing::Values(
6684 // Test case 0: Basic test 1
6685 InstructionFoldingCase<bool>(
6686 Header() +
6687 "; CHECK: OpVectorShuffle\n" +
6688 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 3 6 7\n" +
6689 "; CHECK: OpReturn\n" +
6690 "%main = OpFunction %void None %void_func\n" +
6691 "%main_lab = OpLabel\n" +
6692 "%2 = OpVariable %_ptr_v4double Function\n" +
6693 "%3 = OpVariable %_ptr_v4double Function\n" +
6694 "%4 = OpVariable %_ptr_v4double Function\n" +
6695 "%5 = OpLoad %v4double %2\n" +
6696 "%6 = OpLoad %v4double %3\n" +
6697 "%7 = OpLoad %v4double %4\n" +
6698 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
6699 "%9 = OpVectorShuffle %v4double %7 %8 2 3 4 5\n" +
6700 "OpReturn\n" +
6701 "OpFunctionEnd",
6702 9, true),
6703 // Test case 1: Basic test 2
6704 InstructionFoldingCase<bool>(
6705 Header() +
6706 "; CHECK: OpVectorShuffle\n" +
6707 "; CHECK: OpVectorShuffle {{%\\w+}} %6 %7 0 1 4 5\n" +
6708 "; CHECK: OpReturn\n" +
6709 "%main = OpFunction %void None %void_func\n" +
6710 "%main_lab = OpLabel\n" +
6711 "%2 = OpVariable %_ptr_v4double Function\n" +
6712 "%3 = OpVariable %_ptr_v4double Function\n" +
6713 "%4 = OpVariable %_ptr_v4double Function\n" +
6714 "%5 = OpLoad %v4double %2\n" +
6715 "%6 = OpLoad %v4double %3\n" +
6716 "%7 = OpLoad %v4double %4\n" +
6717 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
6718 "%9 = OpVectorShuffle %v4double %8 %7 2 3 4 5\n" +
6719 "OpReturn\n" +
6720 "OpFunctionEnd",
6721 9, true),
6722 // Test case 2: Basic test 3
6723 InstructionFoldingCase<bool>(
6724 Header() +
6725 "; CHECK: OpVectorShuffle\n" +
6726 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 2 4 5\n" +
6727 "; CHECK: OpReturn\n" +
6728 "%main = OpFunction %void None %void_func\n" +
6729 "%main_lab = OpLabel\n" +
6730 "%2 = OpVariable %_ptr_v4double Function\n" +
6731 "%3 = OpVariable %_ptr_v4double Function\n" +
6732 "%4 = OpVariable %_ptr_v4double Function\n" +
6733 "%5 = OpLoad %v4double %2\n" +
6734 "%6 = OpLoad %v4double %3\n" +
6735 "%7 = OpLoad %v4double %4\n" +
6736 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
6737 "%9 = OpVectorShuffle %v4double %8 %7 1 0 4 5\n" +
6738 "OpReturn\n" +
6739 "OpFunctionEnd",
6740 9, true),
6741 // Test case 3: Basic test 4
6742 InstructionFoldingCase<bool>(
6743 Header() +
6744 "; CHECK: OpVectorShuffle\n" +
6745 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %6 2 3 5 4\n" +
6746 "; CHECK: OpReturn\n" +
6747 "%main = OpFunction %void None %void_func\n" +
6748 "%main_lab = OpLabel\n" +
6749 "%2 = OpVariable %_ptr_v4double Function\n" +
6750 "%3 = OpVariable %_ptr_v4double Function\n" +
6751 "%4 = OpVariable %_ptr_v4double Function\n" +
6752 "%5 = OpLoad %v4double %2\n" +
6753 "%6 = OpLoad %v4double %3\n" +
6754 "%7 = OpLoad %v4double %4\n" +
6755 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
6756 "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 6\n" +
6757 "OpReturn\n" +
6758 "OpFunctionEnd",
6759 9, true),
6760 // Test case 4: Don't fold, need both operands of the feeder.
6761 InstructionFoldingCase<bool>(
6762 Header() +
6763 "%main = OpFunction %void None %void_func\n" +
6764 "%main_lab = OpLabel\n" +
6765 "%2 = OpVariable %_ptr_v4double Function\n" +
6766 "%3 = OpVariable %_ptr_v4double Function\n" +
6767 "%4 = OpVariable %_ptr_v4double Function\n" +
6768 "%5 = OpLoad %v4double %2\n" +
6769 "%6 = OpLoad %v4double %3\n" +
6770 "%7 = OpLoad %v4double %4\n" +
6771 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
6772 "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 5\n" +
6773 "OpReturn\n" +
6774 "OpFunctionEnd",
6775 9, false),
6776 // Test case 5: Don't fold, need both operands of the feeder.
6777 InstructionFoldingCase<bool>(
6778 Header() +
6779 "%main = OpFunction %void None %void_func\n" +
6780 "%main_lab = OpLabel\n" +
6781 "%2 = OpVariable %_ptr_v4double Function\n" +
6782 "%3 = OpVariable %_ptr_v4double Function\n" +
6783 "%4 = OpVariable %_ptr_v4double Function\n" +
6784 "%5 = OpLoad %v4double %2\n" +
6785 "%6 = OpLoad %v4double %3\n" +
6786 "%7 = OpLoad %v4double %4\n" +
6787 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
6788 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
6789 "OpReturn\n" +
6790 "OpFunctionEnd",
6791 9, false),
6792 // Test case 6: Fold, need both operands of the feeder, but they are the same.
6793 InstructionFoldingCase<bool>(
6794 Header() +
6795 "; CHECK: OpVectorShuffle\n" +
6796 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 2 7 5\n" +
6797 "; CHECK: OpReturn\n" +
6798 "%main = OpFunction %void None %void_func\n" +
6799 "%main_lab = OpLabel\n" +
6800 "%2 = OpVariable %_ptr_v4double Function\n" +
6801 "%3 = OpVariable %_ptr_v4double Function\n" +
6802 "%4 = OpVariable %_ptr_v4double Function\n" +
6803 "%5 = OpLoad %v4double %2\n" +
6804 "%6 = OpLoad %v4double %3\n" +
6805 "%7 = OpLoad %v4double %4\n" +
6806 "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
6807 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
6808 "OpReturn\n" +
6809 "OpFunctionEnd",
6810 9, true),
6811 // Test case 7: Fold, need both operands of the feeder, but they are the same.
6812 InstructionFoldingCase<bool>(
6813 Header() +
6814 "; CHECK: OpVectorShuffle\n" +
6815 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 0 5 7\n" +
6816 "; CHECK: OpReturn\n" +
6817 "%main = OpFunction %void None %void_func\n" +
6818 "%main_lab = OpLabel\n" +
6819 "%2 = OpVariable %_ptr_v4double Function\n" +
6820 "%3 = OpVariable %_ptr_v4double Function\n" +
6821 "%4 = OpVariable %_ptr_v4double Function\n" +
6822 "%5 = OpLoad %v4double %2\n" +
6823 "%6 = OpLoad %v4double %3\n" +
6824 "%7 = OpLoad %v4double %4\n" +
6825 "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
6826 "%9 = OpVectorShuffle %v4double %7 %8 2 0 7 5\n" +
6827 "OpReturn\n" +
6828 "OpFunctionEnd",
6829 9, true),
6830 // Test case 8: Replace first operand with a smaller vector.
6831 InstructionFoldingCase<bool>(
6832 Header() +
6833 "; CHECK: OpVectorShuffle\n" +
6834 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 0 5 3\n" +
6835 "; CHECK: OpReturn\n" +
6836 "%main = OpFunction %void None %void_func\n" +
6837 "%main_lab = OpLabel\n" +
6838 "%2 = OpVariable %_ptr_v2double Function\n" +
6839 "%3 = OpVariable %_ptr_v4double Function\n" +
6840 "%4 = OpVariable %_ptr_v4double Function\n" +
6841 "%5 = OpLoad %v2double %2\n" +
6842 "%6 = OpLoad %v4double %3\n" +
6843 "%7 = OpLoad %v4double %4\n" +
6844 "%8 = OpVectorShuffle %v4double %5 %5 0 1 2 3\n" +
6845 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
6846 "OpReturn\n" +
6847 "OpFunctionEnd",
6848 9, true),
6849 // Test case 9: Replace first operand with a larger vector.
6850 InstructionFoldingCase<bool>(
6851 Header() +
6852 "; CHECK: OpVectorShuffle\n" +
6853 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 0 7 5\n" +
6854 "; CHECK: OpReturn\n" +
6855 "%main = OpFunction %void None %void_func\n" +
6856 "%main_lab = OpLabel\n" +
6857 "%2 = OpVariable %_ptr_v4double Function\n" +
6858 "%3 = OpVariable %_ptr_v4double Function\n" +
6859 "%4 = OpVariable %_ptr_v4double Function\n" +
6860 "%5 = OpLoad %v4double %2\n" +
6861 "%6 = OpLoad %v4double %3\n" +
6862 "%7 = OpLoad %v4double %4\n" +
6863 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
6864 "%9 = OpVectorShuffle %v4double %8 %7 1 0 5 3\n" +
6865 "OpReturn\n" +
6866 "OpFunctionEnd",
6867 9, true),
6868 // Test case 10: Replace unused operand with null.
6869 InstructionFoldingCase<bool>(
6870 Header() +
6871 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6872 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6873 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
6874 "; CHECK: OpVectorShuffle\n" +
6875 "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %7 4 2 5 3\n" +
6876 "; CHECK: OpReturn\n" +
6877 "%main = OpFunction %void None %void_func\n" +
6878 "%main_lab = OpLabel\n" +
6879 "%2 = OpVariable %_ptr_v4double Function\n" +
6880 "%3 = OpVariable %_ptr_v4double Function\n" +
6881 "%4 = OpVariable %_ptr_v4double Function\n" +
6882 "%5 = OpLoad %v4double %2\n" +
6883 "%6 = OpLoad %v4double %3\n" +
6884 "%7 = OpLoad %v4double %4\n" +
6885 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
6886 "%9 = OpVectorShuffle %v4double %8 %7 4 2 5 3\n" +
6887 "OpReturn\n" +
6888 "OpFunctionEnd",
6889 9, true),
6890 // Test case 11: Replace unused operand with null.
6891 InstructionFoldingCase<bool>(
6892 Header() +
6893 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6894 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6895 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
6896 "; CHECK: OpVectorShuffle\n" +
6897 "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %5 2 2 5 5\n" +
6898 "; CHECK: OpReturn\n" +
6899 "%main = OpFunction %void None %void_func\n" +
6900 "%main_lab = OpLabel\n" +
6901 "%2 = OpVariable %_ptr_v4double Function\n" +
6902 "%3 = OpVariable %_ptr_v4double Function\n" +
6903 "%5 = OpLoad %v4double %2\n" +
6904 "%6 = OpLoad %v4double %3\n" +
6905 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
6906 "%9 = OpVectorShuffle %v4double %8 %8 2 2 3 3\n" +
6907 "OpReturn\n" +
6908 "OpFunctionEnd",
6909 9, true),
6910 // Test case 12: Replace unused operand with null.
6911 InstructionFoldingCase<bool>(
6912 Header() +
6913 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6914 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6915 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
6916 "; CHECK: OpVectorShuffle\n" +
6917 "; CHECK: OpVectorShuffle {{%\\w+}} %7 [[null]] 2 0 1 3\n" +
6918 "; CHECK: OpReturn\n" +
6919 "%main = OpFunction %void None %void_func\n" +
6920 "%main_lab = OpLabel\n" +
6921 "%2 = OpVariable %_ptr_v4double Function\n" +
6922 "%3 = OpVariable %_ptr_v4double Function\n" +
6923 "%4 = OpVariable %_ptr_v4double Function\n" +
6924 "%5 = OpLoad %v4double %2\n" +
6925 "%6 = OpLoad %v4double %3\n" +
6926 "%7 = OpLoad %v4double %4\n" +
6927 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
6928 "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" +
6929 "OpReturn\n" +
6930 "OpFunctionEnd",
6931 9, true),
6932 // Test case 13: Shuffle with undef literal.
6933 InstructionFoldingCase<bool>(
6934 Header() +
6935 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6936 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6937 "; CHECK: OpVectorShuffle\n" +
6938 "; CHECK: OpVectorShuffle {{%\\w+}} %7 {{%\\w+}} 2 0 1 4294967295\n" +
6939 "; CHECK: OpReturn\n" +
6940 "%main = OpFunction %void None %void_func\n" +
6941 "%main_lab = OpLabel\n" +
6942 "%2 = OpVariable %_ptr_v4double Function\n" +
6943 "%3 = OpVariable %_ptr_v4double Function\n" +
6944 "%4 = OpVariable %_ptr_v4double Function\n" +
6945 "%5 = OpLoad %v4double %2\n" +
6946 "%6 = OpLoad %v4double %3\n" +
6947 "%7 = OpLoad %v4double %4\n" +
6948 "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
6949 "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" +
6950 "OpReturn\n" +
6951 "OpFunctionEnd",
6952 9, true)
6953 ));
6954
6955 using EntryPointFoldingTest =
6956 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
6957
TEST_P(EntryPointFoldingTest,Case)6958 TEST_P(EntryPointFoldingTest, Case) {
6959 const auto& tc = GetParam();
6960
6961 // Build module.
6962 std::unique_ptr<IRContext> context =
6963 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
6964 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
6965 ASSERT_NE(nullptr, context);
6966
6967 // Fold the instruction to test.
6968 Instruction* inst = nullptr;
6969 inst = &*context->module()->entry_points().begin();
6970 assert(inst && "Invalid test. Could not find entry point instruction to fold.");
6971 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
6972 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
6973 EXPECT_EQ(succeeded, tc.expected_result);
6974 if (succeeded) {
6975 Match(tc.test_body, context.get());
6976 }
6977 }
6978
6979 INSTANTIATE_TEST_SUITE_P(OpEntryPointFoldingTest, EntryPointFoldingTest,
6980 ::testing::Values(
6981 // Test case 0: Basic test 1
6982 InstructionFoldingCase<bool>(std::string() +
6983 "; CHECK: OpEntryPoint Fragment %2 \"main\" %3\n" +
6984 "OpCapability Shader\n" +
6985 "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
6986 "OpMemoryModel Logical GLSL450\n" +
6987 "OpEntryPoint Fragment %2 \"main\" %3 %3 %3\n" +
6988 "OpExecutionMode %2 OriginUpperLeft\n" +
6989 "OpSource GLSL 430\n" +
6990 "OpDecorate %3 Location 0\n" +
6991 "%void = OpTypeVoid\n" +
6992 "%5 = OpTypeFunction %void\n" +
6993 "%float = OpTypeFloat 32\n" +
6994 "%v4float = OpTypeVector %float 4\n" +
6995 "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
6996 "%3 = OpVariable %_ptr_Output_v4float Output\n" +
6997 "%int = OpTypeInt 32 1\n" +
6998 "%int_0 = OpConstant %int 0\n" +
6999 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
7000 "%2 = OpFunction %void None %5\n" +
7001 "%12 = OpLabel\n" +
7002 "OpReturn\n" +
7003 "OpFunctionEnd\n",
7004 9, true),
7005 InstructionFoldingCase<bool>(std::string() +
7006 "; CHECK: OpEntryPoint Fragment %2 \"main\" %3 %4\n" +
7007 "OpCapability Shader\n" +
7008 "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
7009 "OpMemoryModel Logical GLSL450\n" +
7010 "OpEntryPoint Fragment %2 \"main\" %3 %4 %3\n" +
7011 "OpExecutionMode %2 OriginUpperLeft\n" +
7012 "OpSource GLSL 430\n" +
7013 "OpDecorate %3 Location 0\n" +
7014 "%void = OpTypeVoid\n" +
7015 "%5 = OpTypeFunction %void\n" +
7016 "%float = OpTypeFloat 32\n" +
7017 "%v4float = OpTypeVector %float 4\n" +
7018 "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
7019 "%3 = OpVariable %_ptr_Output_v4float Output\n" +
7020 "%4 = OpVariable %_ptr_Output_v4float Output\n" +
7021 "%int = OpTypeInt 32 1\n" +
7022 "%int_0 = OpConstant %int 0\n" +
7023 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
7024 "%2 = OpFunction %void None %5\n" +
7025 "%12 = OpLabel\n" +
7026 "OpReturn\n" +
7027 "OpFunctionEnd\n",
7028 9, true),
7029 InstructionFoldingCase<bool>(std::string() +
7030 "; CHECK: OpEntryPoint Fragment %2 \"main\" %4 %3\n" +
7031 "OpCapability Shader\n" +
7032 "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
7033 "OpMemoryModel Logical GLSL450\n" +
7034 "OpEntryPoint Fragment %2 \"main\" %4 %4 %3\n" +
7035 "OpExecutionMode %2 OriginUpperLeft\n" +
7036 "OpSource GLSL 430\n" +
7037 "OpDecorate %3 Location 0\n" +
7038 "%void = OpTypeVoid\n" +
7039 "%5 = OpTypeFunction %void\n" +
7040 "%float = OpTypeFloat 32\n" +
7041 "%v4float = OpTypeVector %float 4\n" +
7042 "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
7043 "%3 = OpVariable %_ptr_Output_v4float Output\n" +
7044 "%4 = OpVariable %_ptr_Output_v4float Output\n" +
7045 "%int = OpTypeInt 32 1\n" +
7046 "%int_0 = OpConstant %int 0\n" +
7047 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
7048 "%2 = OpFunction %void None %5\n" +
7049 "%12 = OpLabel\n" +
7050 "OpReturn\n" +
7051 "OpFunctionEnd\n",
7052 9, true)
7053 ));
7054
7055 using SPV14FoldingTest =
7056 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
7057
TEST_P(SPV14FoldingTest,Case)7058 TEST_P(SPV14FoldingTest, Case) {
7059 const auto& tc = GetParam();
7060
7061 // Build module.
7062 std::unique_ptr<IRContext> context =
7063 BuildModule(SPV_ENV_UNIVERSAL_1_4, nullptr, tc.test_body,
7064 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7065 ASSERT_NE(nullptr, context);
7066
7067 // Fold the instruction to test.
7068 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
7069 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
7070 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
7071 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
7072 EXPECT_EQ(succeeded, tc.expected_result);
7073 if (succeeded) {
7074 Match(tc.test_body, context.get());
7075 }
7076 }
7077
7078 INSTANTIATE_TEST_SUITE_P(SPV14FoldingTest, SPV14FoldingTest,
7079 ::testing::Values(
7080 // Test case 0: select vectors with scalar condition.
7081 InstructionFoldingCase<bool>(std::string() +
7082 "; CHECK-NOT: OpSelect\n" +
7083 "; CHECK: %3 = OpCopyObject {{%\\w+}} %1\n" +
7084 "OpCapability Shader\n" +
7085 "OpCapability Linkage\n" +
7086 "%void = OpTypeVoid\n" +
7087 "%bool = OpTypeBool\n" +
7088 "%true = OpConstantTrue %bool\n" +
7089 "%int = OpTypeInt 32 0\n" +
7090 "%int4 = OpTypeVector %int 4\n" +
7091 "%int_0 = OpConstant %int 0\n" +
7092 "%int_1 = OpConstant %int 1\n" +
7093 "%1 = OpUndef %int4\n" +
7094 "%2 = OpUndef %int4\n" +
7095 "%void_fn = OpTypeFunction %void\n" +
7096 "%func = OpFunction %void None %void_fn\n" +
7097 "%entry = OpLabel\n" +
7098 "%3 = OpSelect %int4 %true %1 %2\n" +
7099 "OpReturn\n" +
7100 "OpFunctionEnd\n"
7101 ,
7102 3, true),
7103 // Test case 1: select struct with scalar condition.
7104 InstructionFoldingCase<bool>(std::string() +
7105 "; CHECK-NOT: OpSelect\n" +
7106 "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
7107 "OpCapability Shader\n" +
7108 "OpCapability Linkage\n" +
7109 "%void = OpTypeVoid\n" +
7110 "%bool = OpTypeBool\n" +
7111 "%true = OpConstantFalse %bool\n" +
7112 "%int = OpTypeInt 32 0\n" +
7113 "%struct = OpTypeStruct %int %int %int %int\n" +
7114 "%int_0 = OpConstant %int 0\n" +
7115 "%int_1 = OpConstant %int 1\n" +
7116 "%1 = OpUndef %struct\n" +
7117 "%2 = OpUndef %struct\n" +
7118 "%void_fn = OpTypeFunction %void\n" +
7119 "%func = OpFunction %void None %void_fn\n" +
7120 "%entry = OpLabel\n" +
7121 "%3 = OpSelect %struct %true %1 %2\n" +
7122 "OpReturn\n" +
7123 "OpFunctionEnd\n"
7124 ,
7125 3, true),
7126 // Test case 1: select array with scalar condition.
7127 InstructionFoldingCase<bool>(std::string() +
7128 "; CHECK-NOT: OpSelect\n" +
7129 "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
7130 "OpCapability Shader\n" +
7131 "OpCapability Linkage\n" +
7132 "%void = OpTypeVoid\n" +
7133 "%bool = OpTypeBool\n" +
7134 "%true = OpConstantFalse %bool\n" +
7135 "%int = OpTypeInt 32 0\n" +
7136 "%int_0 = OpConstant %int 0\n" +
7137 "%int_1 = OpConstant %int 1\n" +
7138 "%int_4 = OpConstant %int 4\n" +
7139 "%array = OpTypeStruct %int %int %int %int\n" +
7140 "%1 = OpUndef %array\n" +
7141 "%2 = OpUndef %array\n" +
7142 "%void_fn = OpTypeFunction %void\n" +
7143 "%func = OpFunction %void None %void_fn\n" +
7144 "%entry = OpLabel\n" +
7145 "%3 = OpSelect %array %true %1 %2\n" +
7146 "OpReturn\n" +
7147 "OpFunctionEnd\n"
7148 ,
7149 3, true)
7150 ));
7151
FloatControlsHeader(const std::string & capabilities)7152 std::string FloatControlsHeader(const std::string& capabilities) {
7153 std::string header = R"(
7154 OpCapability Shader
7155 )" + capabilities + R"(
7156 %void = OpTypeVoid
7157 %float = OpTypeFloat 32
7158 %float_0 = OpConstant %float 0
7159 %float_1 = OpConstant %float 1
7160 %void_fn = OpTypeFunction %void
7161 %func = OpFunction %void None %void_fn
7162 %entry = OpLabel
7163 )";
7164
7165 return header;
7166 }
7167
7168 using FloatControlsFoldingTest =
7169 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
7170
TEST_P(FloatControlsFoldingTest,Case)7171 TEST_P(FloatControlsFoldingTest, Case) {
7172 const auto& tc = GetParam();
7173
7174 // Build module.
7175 std::unique_ptr<IRContext> context =
7176 BuildModule(SPV_ENV_UNIVERSAL_1_4, nullptr, tc.test_body,
7177 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
7178 ASSERT_NE(nullptr, context);
7179
7180 // Fold the instruction to test.
7181 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
7182 Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
7183 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
7184 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
7185 EXPECT_EQ(succeeded, tc.expected_result);
7186 if (succeeded) {
7187 Match(tc.test_body, context.get());
7188 }
7189 }
7190
7191 INSTANTIATE_TEST_SUITE_P(FloatControlsFoldingTest, FloatControlsFoldingTest,
7192 ::testing::Values(
7193 // Test case 0: no folding with DenormPreserve
7194 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormPreserve") +
7195 "%1 = OpFAdd %float %float_0 %float_1\n" +
7196 "OpReturn\n" +
7197 "OpFunctionEnd\n"
7198 ,
7199 1, false),
7200 // Test case 1: no folding with DenormFlushToZero
7201 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormFlushToZero") +
7202 "%1 = OpFAdd %float %float_0 %float_1\n" +
7203 "OpReturn\n" +
7204 "OpFunctionEnd\n"
7205 ,
7206 1, false),
7207 // Test case 2: no folding with SignedZeroInfNanPreserve
7208 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability SignedZeroInfNanPreserve") +
7209 "%1 = OpFAdd %float %float_0 %float_1\n" +
7210 "OpReturn\n" +
7211 "OpFunctionEnd\n"
7212 ,
7213 1, false),
7214 // Test case 3: no folding with RoundingModeRTE
7215 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTE") +
7216 "%1 = OpFAdd %float %float_0 %float_1\n" +
7217 "OpReturn\n" +
7218 "OpFunctionEnd\n"
7219 ,
7220 1, false),
7221 // Test case 4: no folding with RoundingModeRTZ
7222 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTZ") +
7223 "%1 = OpFAdd %float %float_0 %float_1\n" +
7224 "OpReturn\n" +
7225 "OpFunctionEnd\n"
7226 ,
7227 1, false)
7228 ));
7229
ImageOperandsTestBody(const std::string & image_instruction)7230 std::string ImageOperandsTestBody(const std::string& image_instruction) {
7231 std::string body = R"(
7232 OpCapability Shader
7233 OpCapability ImageGatherExtended
7234 OpMemoryModel Logical GLSL450
7235 OpEntryPoint Fragment %main "main"
7236 OpExecutionMode %main OriginUpperLeft
7237 OpDecorate %Texture DescriptorSet 0
7238 OpDecorate %Texture Binding 0
7239 %int = OpTypeInt 32 1
7240 %int_n1 = OpConstant %int -1
7241 %5 = OpConstant %int 0
7242 %float = OpTypeFloat 32
7243 %float_0 = OpConstant %float 0
7244 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
7245 %type_sampled_image = OpTypeSampledImage %type_2d_image
7246 %type_sampler = OpTypeSampler
7247 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
7248 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
7249 %_ptr_int = OpTypePointer Function %int
7250 %v2int = OpTypeVector %int 2
7251 %10 = OpTypeVector %float 4
7252 %void = OpTypeVoid
7253 %22 = OpTypeFunction %void
7254 %v2float = OpTypeVector %float 2
7255 %v3int = OpTypeVector %int 3
7256 %Texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
7257 %gSampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
7258 %101 = OpConstantComposite %v2int %int_n1 %int_n1
7259 %20 = OpConstantComposite %v2float %float_0 %float_0
7260 %main = OpFunction %void None %22
7261 %23 = OpLabel
7262 %var = OpVariable %_ptr_int Function
7263 %88 = OpLoad %type_2d_image %Texture
7264 %val = OpLoad %int %var
7265 %sampler = OpLoad %type_sampler %gSampler
7266 %26 = OpSampledImage %type_sampled_image %88 %sampler
7267 )" + image_instruction + R"(
7268 OpReturn
7269 OpFunctionEnd
7270 )";
7271
7272 return body;
7273 }
7274
7275 INSTANTIATE_TEST_SUITE_P(ImageOperandsBitmaskFoldingTest, MatchingInstructionWithNoResultFoldingTest,
7276 ::testing::Values(
7277 // Test case 0: OpImageFetch without Offset
7278 InstructionFoldingCase<bool>(ImageOperandsTestBody(
7279 "%89 = OpImageFetch %10 %88 %101 Lod %5 \n")
7280 , 89, false),
7281 // Test case 1: OpImageFetch with non-const offset
7282 InstructionFoldingCase<bool>(ImageOperandsTestBody(
7283 "%89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %val \n")
7284 , 89, false),
7285 // Test case 2: OpImageFetch with Lod and Offset
7286 InstructionFoldingCase<bool>(ImageOperandsTestBody(
7287 " %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %101 \n"
7288 "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod|ConstOffset %5 %101 \n")
7289 , 89, true),
7290 // Test case 3: OpImageFetch with Bias and Offset
7291 InstructionFoldingCase<bool>(ImageOperandsTestBody(
7292 " %89 = OpImageFetch %10 %88 %101 Bias|Offset %5 %101 \n"
7293 "; CHECK: %89 = OpImageFetch %10 %88 %101 Bias|ConstOffset %5 %101 \n")
7294 , 89, true),
7295 // Test case 4: OpImageFetch with Grad and Offset.
7296 // Grad adds 2 operands to the instruction.
7297 InstructionFoldingCase<bool>(ImageOperandsTestBody(
7298 " %89 = OpImageFetch %10 %88 %101 Grad|Offset %5 %5 %101 \n"
7299 "; CHECK: %89 = OpImageFetch %10 %88 %101 Grad|ConstOffset %5 %5 %101 \n")
7300 , 89, true),
7301 // Test case 5: OpImageFetch with Offset and MinLod.
7302 // This is an example of a case where the bitmask bit-offset is larger than
7303 // that of the Offset.
7304 InstructionFoldingCase<bool>(ImageOperandsTestBody(
7305 " %89 = OpImageFetch %10 %88 %101 Offset|MinLod %101 %5 \n"
7306 "; CHECK: %89 = OpImageFetch %10 %88 %101 ConstOffset|MinLod %101 %5 \n")
7307 , 89, true),
7308 // Test case 6: OpImageGather with constant Offset
7309 InstructionFoldingCase<bool>(ImageOperandsTestBody(
7310 " %89 = OpImageGather %10 %26 %20 %5 Offset %101 \n"
7311 "; CHECK: %89 = OpImageGather %10 %26 %20 %5 ConstOffset %101 \n")
7312 , 89, true),
7313 // Test case 7: OpImageWrite with constant Offset
7314 InstructionFoldingCase<bool>(ImageOperandsTestBody(
7315 " OpImageWrite %88 %5 %101 Offset %101 \n"
7316 "; CHECK: OpImageWrite %88 %5 %101 ConstOffset %101 \n")
7317 , 0 /* No result-id */, true)
7318 ));
7319
7320 } // namespace
7321 } // namespace opt
7322 } // namespace spvtools
7323