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
6 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include <unordered_set>
17 #include <gmock/gmock.h>
18 #include <gtest/gtest.h>
22 #include "effcee/effcee.h"
25 #include "opt/build_module.h"
26 #include "opt/def_use_manager.h"
27 #include "opt/ir_context.h"
28 #include "opt/module.h"
29 #include "pass_utils.h"
30 #include "spirv-tools/libspirv.hpp"
34 using ::testing::Contains;
36 using namespace spvtools;
37 using spvtools::opt::analysis::DefUseManager;
40 std::string Disassemble(const std::string& original, ir::IRContext* context,
41 uint32_t disassemble_options = 0) {
42 std::vector<uint32_t> optimized_bin;
43 context->module()->ToBinary(&optimized_bin, true);
44 spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
45 SpirvTools tools(target_env);
46 std::string optimized_asm;
48 tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options))
49 << "Disassembling failed for shader:\n"
50 << original << std::endl;
54 void Match(const std::string& original, ir::IRContext* context,
55 uint32_t disassemble_options = 0) {
56 std::string disassembly = Disassemble(original, context, disassemble_options);
57 auto match_result = effcee::Match(disassembly, original);
58 EXPECT_EQ(effcee::Result::Status::Ok, match_result.status())
59 << match_result.message() << "\nChecking result:\n"
64 template <class ResultType>
65 struct InstructionFoldingCase {
66 InstructionFoldingCase(const std::string& tb, uint32_t id, ResultType result)
67 : test_body(tb), id_to_fold(id), expected_result(result) {}
69 std::string test_body;
71 ResultType expected_result;
74 using IntegerInstructionFoldingTest =
75 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
77 TEST_P(IntegerInstructionFoldingTest, Case) {
78 const auto& tc = GetParam();
81 std::unique_ptr<ir::IRContext> context =
82 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
83 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
84 ASSERT_NE(nullptr, context);
86 // Fold the instruction to test.
87 opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
88 ir::Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
89 bool succeeded = opt::FoldInstruction(inst);
91 // Make sure the instruction folded as expected.
92 EXPECT_TRUE(succeeded);
93 if (inst != nullptr) {
94 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
95 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
96 EXPECT_EQ(inst->opcode(), SpvOpConstant);
97 opt::analysis::ConstantManager* const_mrg = context->get_constant_mgr();
98 const opt::analysis::IntConstant* result =
99 const_mrg->GetConstantFromInst(inst)->AsIntConstant();
100 EXPECT_NE(result, nullptr);
101 if (result != nullptr) {
102 EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
107 // Returns a common SPIR-V header for all of the test that follow.
110 #define VEC2_0_ID 102
112 #define FLOAT_0_ID 104
113 #define DOUBLE_0_ID 105
114 #define VEC4_0_ID 106
115 #define DVEC4_0_ID 106
116 #define HALF_0_ID 108
117 const std::string& Header() {
118 static const std::string header = R"(OpCapability Shader
120 %1 = OpExtInstImport "GLSL.std.450"
121 OpMemoryModel Logical GLSL450
122 OpEntryPoint Fragment %main "main"
123 OpExecutionMode %main OriginUpperLeft
127 %void_func = OpTypeFunction %void
129 %float16 = OpTypeFloat 16
130 %float = OpTypeFloat 32
131 %double = OpTypeFloat 64
132 %half = OpTypeFloat 16
133 %101 = OpConstantTrue %bool ; Need a def with an numerical id to define id maps.
134 %true = OpConstantTrue %bool
135 %false = OpConstantFalse %bool
136 %bool_null = OpConstantNull %bool
137 %short = OpTypeInt 16 1
138 %int = OpTypeInt 32 1
139 %long = OpTypeInt 64 1
140 %uint = OpTypeInt 32 0
141 %v2int = OpTypeVector %int 2
142 %v4int = OpTypeVector %int 4
143 %v4float = OpTypeVector %float 4
144 %v4double = OpTypeVector %double 4
145 %v2float = OpTypeVector %float 2
146 %v2bool = OpTypeVector %bool 2
147 %struct_v2int_int_int = OpTypeStruct %v2int %int %int
148 %_ptr_int = OpTypePointer Function %int
149 %_ptr_uint = OpTypePointer Function %uint
150 %_ptr_bool = OpTypePointer Function %bool
151 %_ptr_float = OpTypePointer Function %float
152 %_ptr_double = OpTypePointer Function %double
153 %_ptr_half = OpTypePointer Function %half
154 %_ptr_long = OpTypePointer Function %long
155 %_ptr_v2int = OpTypePointer Function %v2int
156 %_ptr_v4int = OpTypePointer Function %v4int
157 %_ptr_v4float = OpTypePointer Function %v4float
158 %_ptr_v4double = OpTypePointer Function %v4double
159 %_ptr_struct_v2int_int_int = OpTypePointer Function %struct_v2int_int_int
160 %_ptr_v2float = OpTypePointer Function %v2float
161 %short_0 = OpConstant %short 0
162 %short_3 = OpConstant %short 3
163 %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps.
164 %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps.
165 %int_0 = OpConstant %int 0
166 %int_1 = OpConstant %int 1
167 %int_2 = OpConstant %int 2
168 %int_3 = OpConstant %int 3
169 %int_4 = OpConstant %int 4
170 %int_min = OpConstant %int -2147483648
171 %int_max = OpConstant %int 2147483647
172 %long_0 = OpConstant %long 0
173 %long_2 = OpConstant %long 2
174 %long_3 = OpConstant %long 3
175 %uint_0 = OpConstant %uint 0
176 %uint_2 = OpConstant %uint 2
177 %uint_3 = OpConstant %uint 3
178 %uint_4 = OpConstant %uint 4
179 %uint_32 = OpConstant %uint 32
180 %uint_max = OpConstant %uint 4294967295
181 %v2int_undef = OpUndef %v2int
182 %v2int_2_2 = OpConstantComposite %v2int %int_2 %int_2
183 %v2int_2_3 = OpConstantComposite %v2int %int_2 %int_3
184 %v2int_3_2 = OpConstantComposite %v2int %int_3 %int_2
185 %v2int_4_4 = OpConstantComposite %v2int %int_4 %int_4
186 %v2bool_null = OpConstantNull %v2bool
187 %v2bool_true_false = OpConstantComposite %v2bool %true %false
188 %v2bool_false_true = OpConstantComposite %v2bool %false %true
189 %struct_v2int_int_int_null = OpConstantNull %struct_v2int_int_int
190 %v2int_null = OpConstantNull %v2int
191 %102 = OpConstantComposite %v2int %103 %103
192 %v4int_0_0_0_0 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
193 %struct_undef_0_0 = OpConstantComposite %struct_v2int_int_int %v2int_undef %int_0 %int_0
194 %float16_0 = OpConstant %float16 0
195 %float16_1 = OpConstant %float16 1
196 %float16_2 = OpConstant %float16 2
197 %float_n1 = OpConstant %float -1
198 %104 = OpConstant %float 0 ; Need a def with an numerical id to define id maps.
199 %float_0 = OpConstant %float 0
200 %float_half = OpConstant %float 0.5
201 %float_1 = OpConstant %float 1
202 %float_2 = OpConstant %float 2
203 %float_3 = OpConstant %float 3
204 %float_4 = OpConstant %float 4
205 %float_0p5 = OpConstant %float 0.5
206 %v2float_2_2 = OpConstantComposite %v2float %float_2 %float_2
207 %v2float_2_3 = OpConstantComposite %v2float %float_2 %float_3
208 %v2float_3_2 = OpConstantComposite %v2float %float_3 %float_2
209 %v2float_4_4 = OpConstantComposite %v2float %float_4 %float_4
210 %v2float_2_0p5 = OpConstantComposite %v2float %float_2 %float_0p5
211 %v2float_null = OpConstantNull %v2float
212 %double_n1 = OpConstant %double -1
213 %105 = OpConstant %double 0 ; Need a def with an numerical id to define id maps.
214 %double_0 = OpConstant %double 0
215 %double_1 = OpConstant %double 1
216 %double_2 = OpConstant %double 2
217 %double_3 = OpConstant %double 3
218 %float_nan = OpConstant %float -0x1.8p+128
219 %double_nan = OpConstant %double -0x1.8p+1024
220 %108 = OpConstant %half 0
221 %half_1 = OpConstant %half 1
222 %106 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
223 %v4float_0_0_0_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
224 %v4float_0_0_0_1 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
225 %v4float_1_1_1_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
226 %107 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
227 %v4double_0_0_0_0 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
228 %v4double_0_0_0_1 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_1
229 %v4double_1_1_1_1 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_1
236 INSTANTIATE_TEST_CASE_P(TestCase, IntegerInstructionFoldingTest,
238 // Test case 0: fold 0*n
239 InstructionFoldingCase<uint32_t>(
240 Header() + "%main = OpFunction %void None %void_func\n" +
241 "%main_lab = OpLabel\n" +
242 "%n = OpVariable %_ptr_int Function\n" +
243 "%load = OpLoad %int %n\n" +
244 "%2 = OpIMul %int %int_0 %load\n" +
248 // Test case 1: fold n*0
249 InstructionFoldingCase<uint32_t>(
250 Header() + "%main = OpFunction %void None %void_func\n" +
251 "%main_lab = OpLabel\n" +
252 "%n = OpVariable %_ptr_int Function\n" +
253 "%load = OpLoad %int %n\n" +
254 "%2 = OpIMul %int %load %int_0\n" +
258 // Test case 2: fold 0/n (signed)
259 InstructionFoldingCase<uint32_t>(
260 Header() + "%main = OpFunction %void None %void_func\n" +
261 "%main_lab = OpLabel\n" +
262 "%n = OpVariable %_ptr_int Function\n" +
263 "%load = OpLoad %int %n\n" +
264 "%2 = OpSDiv %int %int_0 %load\n" +
268 // Test case 3: fold n/0 (signed)
269 InstructionFoldingCase<uint32_t>(
270 Header() + "%main = OpFunction %void None %void_func\n" +
271 "%main_lab = OpLabel\n" +
272 "%n = OpVariable %_ptr_int Function\n" +
273 "%load = OpLoad %int %n\n" +
274 "%2 = OpSDiv %int %load %int_0\n" +
278 // Test case 4: fold 0/n (unsigned)
279 InstructionFoldingCase<uint32_t>(
280 Header() + "%main = OpFunction %void None %void_func\n" +
281 "%main_lab = OpLabel\n" +
282 "%n = OpVariable %_ptr_uint Function\n" +
283 "%load = OpLoad %uint %n\n" +
284 "%2 = OpUDiv %uint %uint_0 %load\n" +
288 // Test case 5: fold n/0 (unsigned)
289 InstructionFoldingCase<uint32_t>(
290 Header() + "%main = OpFunction %void None %void_func\n" +
291 "%main_lab = OpLabel\n" +
292 "%n = OpVariable %_ptr_int Function\n" +
293 "%load = OpLoad %int %n\n" +
294 "%2 = OpSDiv %int %load %int_0\n" +
298 // Test case 6: fold 0 remainder n
299 InstructionFoldingCase<uint32_t>(
300 Header() + "%main = OpFunction %void None %void_func\n" +
301 "%main_lab = OpLabel\n" +
302 "%n = OpVariable %_ptr_int Function\n" +
303 "%load = OpLoad %int %n\n" +
304 "%2 = OpSRem %int %int_0 %load\n" +
308 // Test case 7: fold n remainder 0
309 InstructionFoldingCase<uint32_t>(
310 Header() + "%main = OpFunction %void None %void_func\n" +
311 "%main_lab = OpLabel\n" +
312 "%n = OpVariable %_ptr_int Function\n" +
313 "%load = OpLoad %int %n\n" +
314 "%2 = OpSRem %int %load %int_0\n" +
318 // Test case 8: fold 0%n (signed)
319 InstructionFoldingCase<uint32_t>(
320 Header() + "%main = OpFunction %void None %void_func\n" +
321 "%main_lab = OpLabel\n" +
322 "%n = OpVariable %_ptr_int Function\n" +
323 "%load = OpLoad %int %n\n" +
324 "%2 = OpSMod %int %int_0 %load\n" +
328 // Test case 9: fold n%0 (signed)
329 InstructionFoldingCase<uint32_t>(
330 Header() + "%main = OpFunction %void None %void_func\n" +
331 "%main_lab = OpLabel\n" +
332 "%n = OpVariable %_ptr_int Function\n" +
333 "%load = OpLoad %int %n\n" +
334 "%2 = OpSMod %int %load %int_0\n" +
338 // Test case 10: fold 0%n (unsigned)
339 InstructionFoldingCase<uint32_t>(
340 Header() + "%main = OpFunction %void None %void_func\n" +
341 "%main_lab = OpLabel\n" +
342 "%n = OpVariable %_ptr_uint Function\n" +
343 "%load = OpLoad %uint %n\n" +
344 "%2 = OpUMod %uint %uint_0 %load\n" +
348 // Test case 11: fold n%0 (unsigned)
349 InstructionFoldingCase<uint32_t>(
350 Header() + "%main = OpFunction %void None %void_func\n" +
351 "%main_lab = OpLabel\n" +
352 "%n = OpVariable %_ptr_uint Function\n" +
353 "%load = OpLoad %uint %n\n" +
354 "%2 = OpUMod %uint %load %uint_0\n" +
358 // Test case 12: fold n << 32
359 InstructionFoldingCase<uint32_t>(
360 Header() + "%main = OpFunction %void None %void_func\n" +
361 "%main_lab = OpLabel\n" +
362 "%n = OpVariable %_ptr_uint Function\n" +
363 "%load = OpLoad %uint %n\n" +
364 "%2 = OpShiftLeftLogical %uint %load %uint_32\n" +
368 // Test case 13: fold n >> 32
369 InstructionFoldingCase<uint32_t>(
370 Header() + "%main = OpFunction %void None %void_func\n" +
371 "%main_lab = OpLabel\n" +
372 "%n = OpVariable %_ptr_uint Function\n" +
373 "%load = OpLoad %uint %n\n" +
374 "%2 = OpShiftRightLogical %uint %load %uint_32\n" +
378 // Test case 14: fold n | 0xFFFFFFFF
379 InstructionFoldingCase<uint32_t>(
380 Header() + "%main = OpFunction %void None %void_func\n" +
381 "%main_lab = OpLabel\n" +
382 "%n = OpVariable %_ptr_uint Function\n" +
383 "%load = OpLoad %uint %n\n" +
384 "%2 = OpBitwiseOr %uint %load %uint_max\n" +
388 // Test case 15: fold 0xFFFFFFFF | n
389 InstructionFoldingCase<uint32_t>(
390 Header() + "%main = OpFunction %void None %void_func\n" +
391 "%main_lab = OpLabel\n" +
392 "%n = OpVariable %_ptr_uint Function\n" +
393 "%load = OpLoad %uint %n\n" +
394 "%2 = OpBitwiseOr %uint %uint_max %load\n" +
398 // Test case 16: fold n & 0
399 InstructionFoldingCase<uint32_t>(
400 Header() + "%main = OpFunction %void None %void_func\n" +
401 "%main_lab = OpLabel\n" +
402 "%n = OpVariable %_ptr_uint Function\n" +
403 "%load = OpLoad %uint %n\n" +
404 "%2 = OpBitwiseAnd %uint %load %uint_0\n" +
411 using IntVectorInstructionFoldingTest =
412 ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint32_t>>>;
414 TEST_P(IntVectorInstructionFoldingTest, Case) {
415 const auto& tc = GetParam();
418 std::unique_ptr<ir::IRContext> context =
419 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
420 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
421 ASSERT_NE(nullptr, context);
423 // Fold the instruction to test.
424 opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
425 ir::Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
426 bool succeeded = opt::FoldInstruction(inst);
428 // Make sure the instruction folded as expected.
429 EXPECT_TRUE(succeeded);
430 if (inst != nullptr) {
431 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
432 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
433 std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
434 EXPECT_THAT(opcodes, Contains(inst->opcode()));
435 opt::analysis::ConstantManager* const_mrg = context->get_constant_mgr();
436 const opt::analysis::Constant* result =
437 const_mrg->GetConstantFromInst(inst);
438 EXPECT_NE(result, nullptr);
439 if (result != nullptr) {
440 const std::vector<const opt::analysis::Constant*>& componenets =
441 result->AsVectorConstant()->GetComponents();
442 EXPECT_EQ(componenets.size(), tc.expected_result.size());
443 for (size_t i = 0; i < componenets.size(); i++) {
444 EXPECT_EQ(tc.expected_result[i], componenets[i]->GetU32());
451 INSTANTIATE_TEST_CASE_P(TestCase, IntVectorInstructionFoldingTest,
453 // Test case 0: fold 0*n
454 InstructionFoldingCase<std::vector<uint32_t>>(
455 Header() + "%main = OpFunction %void None %void_func\n" +
456 "%main_lab = OpLabel\n" +
457 "%n = OpVariable %_ptr_int Function\n" +
458 "%load = OpLoad %int %n\n" +
459 "%2 = OpVectorShuffle %v2int %v2int_2_2 %v2int_2_3 0 3\n" +
463 InstructionFoldingCase<std::vector<uint32_t>>(
464 Header() + "%main = OpFunction %void None %void_func\n" +
465 "%main_lab = OpLabel\n" +
466 "%n = OpVariable %_ptr_int Function\n" +
467 "%load = OpLoad %int %n\n" +
468 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
475 using BooleanInstructionFoldingTest =
476 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
478 TEST_P(BooleanInstructionFoldingTest, Case) {
479 const auto& tc = GetParam();
482 std::unique_ptr<ir::IRContext> context =
483 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
484 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
485 ASSERT_NE(nullptr, context);
487 // Fold the instruction to test.
488 opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
489 ir::Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
490 bool succeeded = opt::FoldInstruction(inst);
492 // Make sure the instruction folded as expected.
493 EXPECT_TRUE(succeeded);
494 if (inst != nullptr) {
495 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
496 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
497 std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
498 EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
499 opt::analysis::ConstantManager* const_mrg = context->get_constant_mgr();
500 const opt::analysis::BoolConstant* result =
501 const_mrg->GetConstantFromInst(inst)->AsBoolConstant();
502 EXPECT_NE(result, nullptr);
503 if (result != nullptr) {
504 EXPECT_EQ(result->value(), tc.expected_result);
510 INSTANTIATE_TEST_CASE_P(TestCase, BooleanInstructionFoldingTest,
512 // Test case 0: fold true || n
513 InstructionFoldingCase<bool>(
514 Header() + "%main = OpFunction %void None %void_func\n" +
515 "%main_lab = OpLabel\n" +
516 "%n = OpVariable %_ptr_bool Function\n" +
517 "%load = OpLoad %bool %n\n" +
518 "%2 = OpLogicalOr %bool %true %load\n" +
522 // Test case 1: fold n || true
523 InstructionFoldingCase<bool>(
524 Header() + "%main = OpFunction %void None %void_func\n" +
525 "%main_lab = OpLabel\n" +
526 "%n = OpVariable %_ptr_bool Function\n" +
527 "%load = OpLoad %bool %n\n" +
528 "%2 = OpLogicalOr %bool %load %true\n" +
532 // Test case 2: fold false && n
533 InstructionFoldingCase<bool>(
534 Header() + "%main = OpFunction %void None %void_func\n" +
535 "%main_lab = OpLabel\n" +
536 "%n = OpVariable %_ptr_bool Function\n" +
537 "%load = OpLoad %bool %n\n" +
538 "%2 = OpLogicalAnd %bool %false %load\n" +
542 // Test case 3: fold n && false
543 InstructionFoldingCase<bool>(
544 Header() + "%main = OpFunction %void None %void_func\n" +
545 "%main_lab = OpLabel\n" +
546 "%n = OpVariable %_ptr_bool Function\n" +
547 "%load = OpLoad %bool %n\n" +
548 "%2 = OpLogicalAnd %bool %load %false\n" +
552 // Test case 4: fold n < 0 (unsigned)
553 InstructionFoldingCase<bool>(
554 Header() + "%main = OpFunction %void None %void_func\n" +
555 "%main_lab = OpLabel\n" +
556 "%n = OpVariable %_ptr_uint Function\n" +
557 "%load = OpLoad %uint %n\n" +
558 "%2 = OpULessThan %bool %load %uint_0\n" +
562 // Test case 5: fold UINT_MAX < n (unsigned)
563 InstructionFoldingCase<bool>(
564 Header() + "%main = OpFunction %void None %void_func\n" +
565 "%main_lab = OpLabel\n" +
566 "%n = OpVariable %_ptr_uint Function\n" +
567 "%load = OpLoad %uint %n\n" +
568 "%2 = OpULessThan %bool %uint_max %load\n" +
572 // Test case 6: fold INT_MAX < n (signed)
573 InstructionFoldingCase<bool>(
574 Header() + "%main = OpFunction %void None %void_func\n" +
575 "%main_lab = OpLabel\n" +
576 "%n = OpVariable %_ptr_int Function\n" +
577 "%load = OpLoad %int %n\n" +
578 "%2 = OpSLessThan %bool %int_max %load\n" +
582 // Test case 7: fold n < INT_MIN (signed)
583 InstructionFoldingCase<bool>(
584 Header() + "%main = OpFunction %void None %void_func\n" +
585 "%main_lab = OpLabel\n" +
586 "%n = OpVariable %_ptr_int Function\n" +
587 "%load = OpLoad %int %n\n" +
588 "%2 = OpSLessThan %bool %load %int_min\n" +
592 // Test case 8: fold 0 > n (unsigned)
593 InstructionFoldingCase<bool>(
594 Header() + "%main = OpFunction %void None %void_func\n" +
595 "%main_lab = OpLabel\n" +
596 "%n = OpVariable %_ptr_uint Function\n" +
597 "%load = OpLoad %uint %n\n" +
598 "%2 = OpUGreaterThan %bool %uint_0 %load\n" +
602 // Test case 9: fold n > UINT_MAX (unsigned)
603 InstructionFoldingCase<bool>(
604 Header() + "%main = OpFunction %void None %void_func\n" +
605 "%main_lab = OpLabel\n" +
606 "%n = OpVariable %_ptr_uint Function\n" +
607 "%load = OpLoad %uint %n\n" +
608 "%2 = OpUGreaterThan %bool %load %uint_max\n" +
612 // Test case 10: fold n > INT_MAX (signed)
613 InstructionFoldingCase<bool>(
614 Header() + "%main = OpFunction %void None %void_func\n" +
615 "%main_lab = OpLabel\n" +
616 "%n = OpVariable %_ptr_int Function\n" +
617 "%load = OpLoad %int %n\n" +
618 "%2 = OpSGreaterThan %bool %load %int_max\n" +
622 // Test case 11: fold INT_MIN > n (signed)
623 InstructionFoldingCase<bool>(
624 Header() + "%main = OpFunction %void None %void_func\n" +
625 "%main_lab = OpLabel\n" +
626 "%n = OpVariable %_ptr_uint Function\n" +
627 "%load = OpLoad %uint %n\n" +
628 "%2 = OpSGreaterThan %bool %int_min %load\n" +
632 // Test case 12: fold 0 <= n (unsigned)
633 InstructionFoldingCase<bool>(
634 Header() + "%main = OpFunction %void None %void_func\n" +
635 "%main_lab = OpLabel\n" +
636 "%n = OpVariable %_ptr_uint Function\n" +
637 "%load = OpLoad %uint %n\n" +
638 "%2 = OpULessThanEqual %bool %uint_0 %load\n" +
642 // Test case 13: fold n <= UINT_MAX (unsigned)
643 InstructionFoldingCase<bool>(
644 Header() + "%main = OpFunction %void None %void_func\n" +
645 "%main_lab = OpLabel\n" +
646 "%n = OpVariable %_ptr_uint Function\n" +
647 "%load = OpLoad %uint %n\n" +
648 "%2 = OpULessThanEqual %bool %load %uint_max\n" +
652 // Test case 14: fold INT_MIN <= n (signed)
653 InstructionFoldingCase<bool>(
654 Header() + "%main = OpFunction %void None %void_func\n" +
655 "%main_lab = OpLabel\n" +
656 "%n = OpVariable %_ptr_int Function\n" +
657 "%load = OpLoad %int %n\n" +
658 "%2 = OpSLessThanEqual %bool %int_min %load\n" +
662 // Test case 15: fold n <= INT_MAX (signed)
663 InstructionFoldingCase<bool>(
664 Header() + "%main = OpFunction %void None %void_func\n" +
665 "%main_lab = OpLabel\n" +
666 "%n = OpVariable %_ptr_int Function\n" +
667 "%load = OpLoad %int %n\n" +
668 "%2 = OpSLessThanEqual %bool %load %int_max\n" +
672 // Test case 16: fold n >= 0 (unsigned)
673 InstructionFoldingCase<bool>(
674 Header() + "%main = OpFunction %void None %void_func\n" +
675 "%main_lab = OpLabel\n" +
676 "%n = OpVariable %_ptr_uint Function\n" +
677 "%load = OpLoad %uint %n\n" +
678 "%2 = OpUGreaterThanEqual %bool %load %uint_0\n" +
682 // Test case 17: fold UINT_MAX >= n (unsigned)
683 InstructionFoldingCase<bool>(
684 Header() + "%main = OpFunction %void None %void_func\n" +
685 "%main_lab = OpLabel\n" +
686 "%n = OpVariable %_ptr_uint Function\n" +
687 "%load = OpLoad %uint %n\n" +
688 "%2 = OpUGreaterThanEqual %bool %uint_max %load\n" +
692 // Test case 18: fold n >= INT_MIN (signed)
693 InstructionFoldingCase<bool>(
694 Header() + "%main = OpFunction %void None %void_func\n" +
695 "%main_lab = OpLabel\n" +
696 "%n = OpVariable %_ptr_int Function\n" +
697 "%load = OpLoad %int %n\n" +
698 "%2 = OpSGreaterThanEqual %bool %load %int_min\n" +
702 // Test case 19: fold INT_MAX >= n (signed)
703 InstructionFoldingCase<bool>(
704 Header() + "%main = OpFunction %void None %void_func\n" +
705 "%main_lab = OpLabel\n" +
706 "%n = OpVariable %_ptr_int Function\n" +
707 "%load = OpLoad %int %n\n" +
708 "%2 = OpSGreaterThanEqual %bool %int_max %load\n" +
715 using FloatInstructionFoldingTest =
716 ::testing::TestWithParam<InstructionFoldingCase<float>>;
718 TEST_P(FloatInstructionFoldingTest, Case) {
719 const auto& tc = GetParam();
722 std::unique_ptr<ir::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);
727 // Fold the instruction to test.
728 opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
729 ir::Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
730 bool succeeded = opt::FoldInstruction(inst);
732 // Make sure the instruction folded as expected.
733 EXPECT_TRUE(succeeded);
734 if (inst != nullptr) {
735 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
736 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
737 EXPECT_EQ(inst->opcode(), SpvOpConstant);
738 opt::analysis::ConstantManager* const_mrg = context->get_constant_mgr();
739 const opt::analysis::FloatConstant* result =
740 const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
741 EXPECT_NE(result, nullptr);
742 if (result != nullptr) {
743 EXPECT_EQ(result->GetFloatValue(), tc.expected_result);
748 // Not testing NaNs because there are no expectations concerning NaNs according
749 // to the "Precision and Operation of SPIR-V Instructions" section of the Vulkan
753 INSTANTIATE_TEST_CASE_P(FloatConstantFoldingTest, FloatInstructionFoldingTest,
755 // Test case 0: Fold 2.0 - 1.0
756 InstructionFoldingCase<float>(
757 Header() + "%main = OpFunction %void None %void_func\n" +
758 "%main_lab = OpLabel\n" +
759 "%2 = OpFSub %float %float_2 %float_1\n" +
763 // Test case 1: Fold 2.0 + 1.0
764 InstructionFoldingCase<float>(
765 Header() + "%main = OpFunction %void None %void_func\n" +
766 "%main_lab = OpLabel\n" +
767 "%2 = OpFAdd %float %float_2 %float_1\n" +
771 // Test case 2: Fold 3.0 * 2.0
772 InstructionFoldingCase<float>(
773 Header() + "%main = OpFunction %void None %void_func\n" +
774 "%main_lab = OpLabel\n" +
775 "%2 = OpFMul %float %float_3 %float_2\n" +
779 // Test case 3: Fold 1.0 / 2.0
780 InstructionFoldingCase<float>(
781 Header() + "%main = OpFunction %void None %void_func\n" +
782 "%main_lab = OpLabel\n" +
783 "%2 = OpFDiv %float %float_1 %float_2\n" +
787 // Test case 4: Fold 1.0 / 0.0
788 InstructionFoldingCase<float>(
789 Header() + "%main = OpFunction %void None %void_func\n" +
790 "%main_lab = OpLabel\n" +
791 "%2 = OpFDiv %float %float_1 %float_0\n" +
794 2, std::numeric_limits<float>::infinity()),
795 // Test case 5: Fold -1.0 / 0.0
796 InstructionFoldingCase<float>(
797 Header() + "%main = OpFunction %void None %void_func\n" +
798 "%main_lab = OpLabel\n" +
799 "%2 = OpFDiv %float %float_n1 %float_0\n" +
802 2, -std::numeric_limits<float>::infinity())
806 using DoubleInstructionFoldingTest =
807 ::testing::TestWithParam<InstructionFoldingCase<double>>;
809 TEST_P(DoubleInstructionFoldingTest, Case) {
810 const auto& tc = GetParam();
813 std::unique_ptr<ir::IRContext> context =
814 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
815 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
816 ASSERT_NE(nullptr, context);
818 // Fold the instruction to test.
819 opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
820 ir::Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
821 bool succeeded = opt::FoldInstruction(inst);
823 // Make sure the instruction folded as expected.
824 EXPECT_TRUE(succeeded);
825 if (inst != nullptr) {
826 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
827 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
828 EXPECT_EQ(inst->opcode(), SpvOpConstant);
829 opt::analysis::ConstantManager* const_mrg = context->get_constant_mgr();
830 const opt::analysis::FloatConstant* result =
831 const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
832 EXPECT_NE(result, nullptr);
833 if (result != nullptr) {
834 EXPECT_EQ(result->GetDoubleValue(), tc.expected_result);
840 INSTANTIATE_TEST_CASE_P(DoubleConstantFoldingTest, DoubleInstructionFoldingTest,
842 // Test case 0: Fold 2.0 - 1.0
843 InstructionFoldingCase<double>(
844 Header() + "%main = OpFunction %void None %void_func\n" +
845 "%main_lab = OpLabel\n" +
846 "%2 = OpFSub %double %double_2 %double_1\n" +
850 // Test case 1: Fold 2.0 + 1.0
851 InstructionFoldingCase<double>(
852 Header() + "%main = OpFunction %void None %void_func\n" +
853 "%main_lab = OpLabel\n" +
854 "%2 = OpFAdd %double %double_2 %double_1\n" +
858 // Test case 2: Fold 3.0 * 2.0
859 InstructionFoldingCase<double>(
860 Header() + "%main = OpFunction %void None %void_func\n" +
861 "%main_lab = OpLabel\n" +
862 "%2 = OpFMul %double %double_3 %double_2\n" +
866 // Test case 3: Fold 1.0 / 2.0
867 InstructionFoldingCase<double>(
868 Header() + "%main = OpFunction %void None %void_func\n" +
869 "%main_lab = OpLabel\n" +
870 "%2 = OpFDiv %double %double_1 %double_2\n" +
874 // Test case 4: Fold 1.0 / 0.0
875 InstructionFoldingCase<double>(
876 Header() + "%main = OpFunction %void None %void_func\n" +
877 "%main_lab = OpLabel\n" +
878 "%2 = OpFDiv %double %double_1 %double_0\n" +
881 2, std::numeric_limits<double>::infinity()),
882 // Test case 4: Fold -1.0 / 0.0
883 InstructionFoldingCase<double>(
884 Header() + "%main = OpFunction %void None %void_func\n" +
885 "%main_lab = OpLabel\n" +
886 "%2 = OpFDiv %double %double_n1 %double_0\n" +
889 2, -std::numeric_limits<double>::infinity())
894 INSTANTIATE_TEST_CASE_P(DoubleOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
896 // Test case 0: fold 1.0 == 2.0
897 InstructionFoldingCase<bool>(
898 Header() + "%main = OpFunction %void None %void_func\n" +
899 "%main_lab = OpLabel\n" +
900 "%2 = OpFOrdEqual %bool %double_1 %double_2\n" +
904 // Test case 1: fold 1.0 != 2.0
905 InstructionFoldingCase<bool>(
906 Header() + "%main = OpFunction %void None %void_func\n" +
907 "%main_lab = OpLabel\n" +
908 "%2 = OpFOrdNotEqual %bool %double_1 %double_2\n" +
912 // Test case 2: fold 1.0 < 2.0
913 InstructionFoldingCase<bool>(
914 Header() + "%main = OpFunction %void None %void_func\n" +
915 "%main_lab = OpLabel\n" +
916 "%2 = OpFOrdLessThan %bool %double_1 %double_2\n" +
920 // Test case 3: fold 1.0 > 2.0
921 InstructionFoldingCase<bool>(
922 Header() + "%main = OpFunction %void None %void_func\n" +
923 "%main_lab = OpLabel\n" +
924 "%2 = OpFOrdGreaterThan %bool %double_1 %double_2\n" +
928 // Test case 4: fold 1.0 <= 2.0
929 InstructionFoldingCase<bool>(
930 Header() + "%main = OpFunction %void None %void_func\n" +
931 "%main_lab = OpLabel\n" +
932 "%2 = OpFOrdLessThanEqual %bool %double_1 %double_2\n" +
936 // Test case 5: fold 1.0 >= 2.0
937 InstructionFoldingCase<bool>(
938 Header() + "%main = OpFunction %void None %void_func\n" +
939 "%main_lab = OpLabel\n" +
940 "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_2\n" +
944 // Test case 6: fold 1.0 == 1.0
945 InstructionFoldingCase<bool>(
946 Header() + "%main = OpFunction %void None %void_func\n" +
947 "%main_lab = OpLabel\n" +
948 "%2 = OpFOrdEqual %bool %double_1 %double_1\n" +
952 // Test case 7: fold 1.0 != 1.0
953 InstructionFoldingCase<bool>(
954 Header() + "%main = OpFunction %void None %void_func\n" +
955 "%main_lab = OpLabel\n" +
956 "%2 = OpFOrdNotEqual %bool %double_1 %double_1\n" +
960 // Test case 8: fold 1.0 < 1.0
961 InstructionFoldingCase<bool>(
962 Header() + "%main = OpFunction %void None %void_func\n" +
963 "%main_lab = OpLabel\n" +
964 "%2 = OpFOrdLessThan %bool %double_1 %double_1\n" +
968 // Test case 9: fold 1.0 > 1.0
969 InstructionFoldingCase<bool>(
970 Header() + "%main = OpFunction %void None %void_func\n" +
971 "%main_lab = OpLabel\n" +
972 "%2 = OpFOrdGreaterThan %bool %double_1 %double_1\n" +
976 // Test case 10: fold 1.0 <= 1.0
977 InstructionFoldingCase<bool>(
978 Header() + "%main = OpFunction %void None %void_func\n" +
979 "%main_lab = OpLabel\n" +
980 "%2 = OpFOrdLessThanEqual %bool %double_1 %double_1\n" +
984 // Test case 11: fold 1.0 >= 1.0
985 InstructionFoldingCase<bool>(
986 Header() + "%main = OpFunction %void None %void_func\n" +
987 "%main_lab = OpLabel\n" +
988 "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_1\n" +
992 // Test case 12: fold 2.0 < 1.0
993 InstructionFoldingCase<bool>(
994 Header() + "%main = OpFunction %void None %void_func\n" +
995 "%main_lab = OpLabel\n" +
996 "%2 = OpFOrdLessThan %bool %double_2 %double_1\n" +
1000 // Test case 13: fold 2.0 > 1.0
1001 InstructionFoldingCase<bool>(
1002 Header() + "%main = OpFunction %void None %void_func\n" +
1003 "%main_lab = OpLabel\n" +
1004 "%2 = OpFOrdGreaterThan %bool %double_2 %double_1\n" +
1008 // Test case 14: fold 2.0 <= 1.0
1009 InstructionFoldingCase<bool>(
1010 Header() + "%main = OpFunction %void None %void_func\n" +
1011 "%main_lab = OpLabel\n" +
1012 "%2 = OpFOrdLessThanEqual %bool %double_2 %double_1\n" +
1016 // Test case 15: fold 2.0 >= 1.0
1017 InstructionFoldingCase<bool>(
1018 Header() + "%main = OpFunction %void None %void_func\n" +
1019 "%main_lab = OpLabel\n" +
1020 "%2 = OpFOrdGreaterThanEqual %bool %double_2 %double_1\n" +
1026 INSTANTIATE_TEST_CASE_P(DoubleUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
1028 // Test case 0: fold 1.0 == 2.0
1029 InstructionFoldingCase<bool>(
1030 Header() + "%main = OpFunction %void None %void_func\n" +
1031 "%main_lab = OpLabel\n" +
1032 "%2 = OpFUnordEqual %bool %double_1 %double_2\n" +
1036 // Test case 1: fold 1.0 != 2.0
1037 InstructionFoldingCase<bool>(
1038 Header() + "%main = OpFunction %void None %void_func\n" +
1039 "%main_lab = OpLabel\n" +
1040 "%2 = OpFUnordNotEqual %bool %double_1 %double_2\n" +
1044 // Test case 2: fold 1.0 < 2.0
1045 InstructionFoldingCase<bool>(
1046 Header() + "%main = OpFunction %void None %void_func\n" +
1047 "%main_lab = OpLabel\n" +
1048 "%2 = OpFUnordLessThan %bool %double_1 %double_2\n" +
1052 // Test case 3: fold 1.0 > 2.0
1053 InstructionFoldingCase<bool>(
1054 Header() + "%main = OpFunction %void None %void_func\n" +
1055 "%main_lab = OpLabel\n" +
1056 "%2 = OpFUnordGreaterThan %bool %double_1 %double_2\n" +
1060 // Test case 4: fold 1.0 <= 2.0
1061 InstructionFoldingCase<bool>(
1062 Header() + "%main = OpFunction %void None %void_func\n" +
1063 "%main_lab = OpLabel\n" +
1064 "%2 = OpFUnordLessThanEqual %bool %double_1 %double_2\n" +
1068 // Test case 5: fold 1.0 >= 2.0
1069 InstructionFoldingCase<bool>(
1070 Header() + "%main = OpFunction %void None %void_func\n" +
1071 "%main_lab = OpLabel\n" +
1072 "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_2\n" +
1076 // Test case 6: fold 1.0 == 1.0
1077 InstructionFoldingCase<bool>(
1078 Header() + "%main = OpFunction %void None %void_func\n" +
1079 "%main_lab = OpLabel\n" +
1080 "%2 = OpFUnordEqual %bool %double_1 %double_1\n" +
1084 // Test case 7: fold 1.0 != 1.0
1085 InstructionFoldingCase<bool>(
1086 Header() + "%main = OpFunction %void None %void_func\n" +
1087 "%main_lab = OpLabel\n" +
1088 "%2 = OpFUnordNotEqual %bool %double_1 %double_1\n" +
1092 // Test case 8: fold 1.0 < 1.0
1093 InstructionFoldingCase<bool>(
1094 Header() + "%main = OpFunction %void None %void_func\n" +
1095 "%main_lab = OpLabel\n" +
1096 "%2 = OpFUnordLessThan %bool %double_1 %double_1\n" +
1100 // Test case 9: fold 1.0 > 1.0
1101 InstructionFoldingCase<bool>(
1102 Header() + "%main = OpFunction %void None %void_func\n" +
1103 "%main_lab = OpLabel\n" +
1104 "%2 = OpFUnordGreaterThan %bool %double_1 %double_1\n" +
1108 // Test case 10: fold 1.0 <= 1.0
1109 InstructionFoldingCase<bool>(
1110 Header() + "%main = OpFunction %void None %void_func\n" +
1111 "%main_lab = OpLabel\n" +
1112 "%2 = OpFUnordLessThanEqual %bool %double_1 %double_1\n" +
1116 // Test case 11: fold 1.0 >= 1.0
1117 InstructionFoldingCase<bool>(
1118 Header() + "%main = OpFunction %void None %void_func\n" +
1119 "%main_lab = OpLabel\n" +
1120 "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_1\n" +
1124 // Test case 12: fold 2.0 < 1.0
1125 InstructionFoldingCase<bool>(
1126 Header() + "%main = OpFunction %void None %void_func\n" +
1127 "%main_lab = OpLabel\n" +
1128 "%2 = OpFUnordLessThan %bool %double_2 %double_1\n" +
1132 // Test case 13: fold 2.0 > 1.0
1133 InstructionFoldingCase<bool>(
1134 Header() + "%main = OpFunction %void None %void_func\n" +
1135 "%main_lab = OpLabel\n" +
1136 "%2 = OpFUnordGreaterThan %bool %double_2 %double_1\n" +
1140 // Test case 14: fold 2.0 <= 1.0
1141 InstructionFoldingCase<bool>(
1142 Header() + "%main = OpFunction %void None %void_func\n" +
1143 "%main_lab = OpLabel\n" +
1144 "%2 = OpFUnordLessThanEqual %bool %double_2 %double_1\n" +
1148 // Test case 15: fold 2.0 >= 1.0
1149 InstructionFoldingCase<bool>(
1150 Header() + "%main = OpFunction %void None %void_func\n" +
1151 "%main_lab = OpLabel\n" +
1152 "%2 = OpFUnordGreaterThanEqual %bool %double_2 %double_1\n" +
1158 INSTANTIATE_TEST_CASE_P(FloatOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
1160 // Test case 0: fold 1.0 == 2.0
1161 InstructionFoldingCase<bool>(
1162 Header() + "%main = OpFunction %void None %void_func\n" +
1163 "%main_lab = OpLabel\n" +
1164 "%2 = OpFOrdEqual %bool %float_1 %float_2\n" +
1168 // Test case 1: fold 1.0 != 2.0
1169 InstructionFoldingCase<bool>(
1170 Header() + "%main = OpFunction %void None %void_func\n" +
1171 "%main_lab = OpLabel\n" +
1172 "%2 = OpFOrdNotEqual %bool %float_1 %float_2\n" +
1176 // Test case 2: fold 1.0 < 2.0
1177 InstructionFoldingCase<bool>(
1178 Header() + "%main = OpFunction %void None %void_func\n" +
1179 "%main_lab = OpLabel\n" +
1180 "%2 = OpFOrdLessThan %bool %float_1 %float_2\n" +
1184 // Test case 3: fold 1.0 > 2.0
1185 InstructionFoldingCase<bool>(
1186 Header() + "%main = OpFunction %void None %void_func\n" +
1187 "%main_lab = OpLabel\n" +
1188 "%2 = OpFOrdGreaterThan %bool %float_1 %float_2\n" +
1192 // Test case 4: fold 1.0 <= 2.0
1193 InstructionFoldingCase<bool>(
1194 Header() + "%main = OpFunction %void None %void_func\n" +
1195 "%main_lab = OpLabel\n" +
1196 "%2 = OpFOrdLessThanEqual %bool %float_1 %float_2\n" +
1200 // Test case 5: fold 1.0 >= 2.0
1201 InstructionFoldingCase<bool>(
1202 Header() + "%main = OpFunction %void None %void_func\n" +
1203 "%main_lab = OpLabel\n" +
1204 "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_2\n" +
1208 // Test case 6: fold 1.0 == 1.0
1209 InstructionFoldingCase<bool>(
1210 Header() + "%main = OpFunction %void None %void_func\n" +
1211 "%main_lab = OpLabel\n" +
1212 "%2 = OpFOrdEqual %bool %float_1 %float_1\n" +
1216 // Test case 7: fold 1.0 != 1.0
1217 InstructionFoldingCase<bool>(
1218 Header() + "%main = OpFunction %void None %void_func\n" +
1219 "%main_lab = OpLabel\n" +
1220 "%2 = OpFOrdNotEqual %bool %float_1 %float_1\n" +
1224 // Test case 8: fold 1.0 < 1.0
1225 InstructionFoldingCase<bool>(
1226 Header() + "%main = OpFunction %void None %void_func\n" +
1227 "%main_lab = OpLabel\n" +
1228 "%2 = OpFOrdLessThan %bool %float_1 %float_1\n" +
1232 // Test case 9: fold 1.0 > 1.0
1233 InstructionFoldingCase<bool>(
1234 Header() + "%main = OpFunction %void None %void_func\n" +
1235 "%main_lab = OpLabel\n" +
1236 "%2 = OpFOrdGreaterThan %bool %float_1 %float_1\n" +
1240 // Test case 10: fold 1.0 <= 1.0
1241 InstructionFoldingCase<bool>(
1242 Header() + "%main = OpFunction %void None %void_func\n" +
1243 "%main_lab = OpLabel\n" +
1244 "%2 = OpFOrdLessThanEqual %bool %float_1 %float_1\n" +
1248 // Test case 11: fold 1.0 >= 1.0
1249 InstructionFoldingCase<bool>(
1250 Header() + "%main = OpFunction %void None %void_func\n" +
1251 "%main_lab = OpLabel\n" +
1252 "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_1\n" +
1256 // Test case 12: fold 2.0 < 1.0
1257 InstructionFoldingCase<bool>(
1258 Header() + "%main = OpFunction %void None %void_func\n" +
1259 "%main_lab = OpLabel\n" +
1260 "%2 = OpFOrdLessThan %bool %float_2 %float_1\n" +
1264 // Test case 13: fold 2.0 > 1.0
1265 InstructionFoldingCase<bool>(
1266 Header() + "%main = OpFunction %void None %void_func\n" +
1267 "%main_lab = OpLabel\n" +
1268 "%2 = OpFOrdGreaterThan %bool %float_2 %float_1\n" +
1272 // Test case 14: fold 2.0 <= 1.0
1273 InstructionFoldingCase<bool>(
1274 Header() + "%main = OpFunction %void None %void_func\n" +
1275 "%main_lab = OpLabel\n" +
1276 "%2 = OpFOrdLessThanEqual %bool %float_2 %float_1\n" +
1280 // Test case 15: fold 2.0 >= 1.0
1281 InstructionFoldingCase<bool>(
1282 Header() + "%main = OpFunction %void None %void_func\n" +
1283 "%main_lab = OpLabel\n" +
1284 "%2 = OpFOrdGreaterThanEqual %bool %float_2 %float_1\n" +
1290 INSTANTIATE_TEST_CASE_P(FloatUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
1292 // Test case 0: fold 1.0 == 2.0
1293 InstructionFoldingCase<bool>(
1294 Header() + "%main = OpFunction %void None %void_func\n" +
1295 "%main_lab = OpLabel\n" +
1296 "%2 = OpFUnordEqual %bool %float_1 %float_2\n" +
1300 // Test case 1: fold 1.0 != 2.0
1301 InstructionFoldingCase<bool>(
1302 Header() + "%main = OpFunction %void None %void_func\n" +
1303 "%main_lab = OpLabel\n" +
1304 "%2 = OpFUnordNotEqual %bool %float_1 %float_2\n" +
1308 // Test case 2: fold 1.0 < 2.0
1309 InstructionFoldingCase<bool>(
1310 Header() + "%main = OpFunction %void None %void_func\n" +
1311 "%main_lab = OpLabel\n" +
1312 "%2 = OpFUnordLessThan %bool %float_1 %float_2\n" +
1316 // Test case 3: fold 1.0 > 2.0
1317 InstructionFoldingCase<bool>(
1318 Header() + "%main = OpFunction %void None %void_func\n" +
1319 "%main_lab = OpLabel\n" +
1320 "%2 = OpFUnordGreaterThan %bool %float_1 %float_2\n" +
1324 // Test case 4: fold 1.0 <= 2.0
1325 InstructionFoldingCase<bool>(
1326 Header() + "%main = OpFunction %void None %void_func\n" +
1327 "%main_lab = OpLabel\n" +
1328 "%2 = OpFUnordLessThanEqual %bool %float_1 %float_2\n" +
1332 // Test case 5: fold 1.0 >= 2.0
1333 InstructionFoldingCase<bool>(
1334 Header() + "%main = OpFunction %void None %void_func\n" +
1335 "%main_lab = OpLabel\n" +
1336 "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_2\n" +
1340 // Test case 6: fold 1.0 == 1.0
1341 InstructionFoldingCase<bool>(
1342 Header() + "%main = OpFunction %void None %void_func\n" +
1343 "%main_lab = OpLabel\n" +
1344 "%2 = OpFUnordEqual %bool %float_1 %float_1\n" +
1348 // Test case 7: fold 1.0 != 1.0
1349 InstructionFoldingCase<bool>(
1350 Header() + "%main = OpFunction %void None %void_func\n" +
1351 "%main_lab = OpLabel\n" +
1352 "%2 = OpFUnordNotEqual %bool %float_1 %float_1\n" +
1356 // Test case 8: fold 1.0 < 1.0
1357 InstructionFoldingCase<bool>(
1358 Header() + "%main = OpFunction %void None %void_func\n" +
1359 "%main_lab = OpLabel\n" +
1360 "%2 = OpFUnordLessThan %bool %float_1 %float_1\n" +
1364 // Test case 9: fold 1.0 > 1.0
1365 InstructionFoldingCase<bool>(
1366 Header() + "%main = OpFunction %void None %void_func\n" +
1367 "%main_lab = OpLabel\n" +
1368 "%2 = OpFUnordGreaterThan %bool %float_1 %float_1\n" +
1372 // Test case 10: fold 1.0 <= 1.0
1373 InstructionFoldingCase<bool>(
1374 Header() + "%main = OpFunction %void None %void_func\n" +
1375 "%main_lab = OpLabel\n" +
1376 "%2 = OpFUnordLessThanEqual %bool %float_1 %float_1\n" +
1380 // Test case 11: fold 1.0 >= 1.0
1381 InstructionFoldingCase<bool>(
1382 Header() + "%main = OpFunction %void None %void_func\n" +
1383 "%main_lab = OpLabel\n" +
1384 "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_1\n" +
1388 // Test case 12: fold 2.0 < 1.0
1389 InstructionFoldingCase<bool>(
1390 Header() + "%main = OpFunction %void None %void_func\n" +
1391 "%main_lab = OpLabel\n" +
1392 "%2 = OpFUnordLessThan %bool %float_2 %float_1\n" +
1396 // Test case 13: fold 2.0 > 1.0
1397 InstructionFoldingCase<bool>(
1398 Header() + "%main = OpFunction %void None %void_func\n" +
1399 "%main_lab = OpLabel\n" +
1400 "%2 = OpFUnordGreaterThan %bool %float_2 %float_1\n" +
1404 // Test case 14: fold 2.0 <= 1.0
1405 InstructionFoldingCase<bool>(
1406 Header() + "%main = OpFunction %void None %void_func\n" +
1407 "%main_lab = OpLabel\n" +
1408 "%2 = OpFUnordLessThanEqual %bool %float_2 %float_1\n" +
1412 // Test case 15: fold 2.0 >= 1.0
1413 InstructionFoldingCase<bool>(
1414 Header() + "%main = OpFunction %void None %void_func\n" +
1415 "%main_lab = OpLabel\n" +
1416 "%2 = OpFUnordGreaterThanEqual %bool %float_2 %float_1\n" +
1422 INSTANTIATE_TEST_CASE_P(DoubleNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
1424 // Test case 0: fold NaN == 0 (ord)
1425 InstructionFoldingCase<bool>(
1426 Header() + "%main = OpFunction %void None %void_func\n" +
1427 "%main_lab = OpLabel\n" +
1428 "%2 = OpFOrdEqual %bool %double_nan %double_0\n" +
1432 // Test case 1: fold NaN == NaN (unord)
1433 InstructionFoldingCase<bool>(
1434 Header() + "%main = OpFunction %void None %void_func\n" +
1435 "%main_lab = OpLabel\n" +
1436 "%2 = OpFUnordEqual %bool %double_nan %double_0\n" +
1440 // Test case 2: fold NaN != NaN (ord)
1441 InstructionFoldingCase<bool>(
1442 Header() + "%main = OpFunction %void None %void_func\n" +
1443 "%main_lab = OpLabel\n" +
1444 "%2 = OpFOrdNotEqual %bool %double_nan %double_0\n" +
1448 // Test case 3: fold NaN != NaN (unord)
1449 InstructionFoldingCase<bool>(
1450 Header() + "%main = OpFunction %void None %void_func\n" +
1451 "%main_lab = OpLabel\n" +
1452 "%2 = OpFUnordNotEqual %bool %double_nan %double_0\n" +
1458 INSTANTIATE_TEST_CASE_P(FloatNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
1460 // Test case 0: fold NaN == 0 (ord)
1461 InstructionFoldingCase<bool>(
1462 Header() + "%main = OpFunction %void None %void_func\n" +
1463 "%main_lab = OpLabel\n" +
1464 "%2 = OpFOrdEqual %bool %float_nan %float_0\n" +
1468 // Test case 1: fold NaN == NaN (unord)
1469 InstructionFoldingCase<bool>(
1470 Header() + "%main = OpFunction %void None %void_func\n" +
1471 "%main_lab = OpLabel\n" +
1472 "%2 = OpFUnordEqual %bool %float_nan %float_0\n" +
1476 // Test case 2: fold NaN != NaN (ord)
1477 InstructionFoldingCase<bool>(
1478 Header() + "%main = OpFunction %void None %void_func\n" +
1479 "%main_lab = OpLabel\n" +
1480 "%2 = OpFOrdNotEqual %bool %float_nan %float_0\n" +
1484 // Test case 3: fold NaN != NaN (unord)
1485 InstructionFoldingCase<bool>(
1486 Header() + "%main = OpFunction %void None %void_func\n" +
1487 "%main_lab = OpLabel\n" +
1488 "%2 = OpFUnordNotEqual %bool %float_nan %float_0\n" +
1495 template <class ResultType>
1496 struct InstructionFoldingCaseWithMap {
1497 InstructionFoldingCaseWithMap(const std::string& tb, uint32_t id,
1499 std::function<uint32_t(uint32_t)> map)
1500 : test_body(tb), id_to_fold(id), expected_result(result), id_map(map) {}
1502 std::string test_body;
1503 uint32_t id_to_fold;
1504 ResultType expected_result;
1505 std::function<uint32_t(uint32_t)> id_map;
1508 using IntegerInstructionFoldingTestWithMap =
1509 ::testing::TestWithParam<InstructionFoldingCaseWithMap<uint32_t>>;
1511 TEST_P(IntegerInstructionFoldingTestWithMap, Case) {
1512 const auto& tc = GetParam();
1515 std::unique_ptr<ir::IRContext> context =
1516 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
1517 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1518 ASSERT_NE(nullptr, context);
1520 // Fold the instruction to test.
1521 opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
1522 ir::Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
1523 inst = opt::FoldInstructionToConstant(inst, tc.id_map);
1525 // Make sure the instruction folded as expected.
1526 EXPECT_NE(inst, nullptr);
1527 if (inst != nullptr) {
1528 EXPECT_EQ(inst->opcode(), SpvOpConstant);
1529 opt::analysis::ConstantManager* const_mrg = context->get_constant_mgr();
1530 const opt::analysis::IntConstant* result =
1531 const_mrg->GetConstantFromInst(inst)->AsIntConstant();
1532 EXPECT_NE(result, nullptr);
1533 if (result != nullptr) {
1534 EXPECT_EQ(result->GetU32BitValue(), tc.expected_result);
1539 INSTANTIATE_TEST_CASE_P(TestCase, IntegerInstructionFoldingTestWithMap,
1541 // Test case 0: fold %3 = 0; %3 * n
1542 InstructionFoldingCaseWithMap<uint32_t>(
1543 Header() + "%main = OpFunction %void None %void_func\n" +
1544 "%main_lab = OpLabel\n" +
1545 "%n = OpVariable %_ptr_int Function\n" +
1546 "%load = OpLoad %int %n\n" +
1547 "%3 = OpCopyObject %int %int_0\n"
1548 "%2 = OpIMul %int %3 %load\n" +
1551 2, 0, [](uint32_t id) {return (id == 3 ? INT_0_ID : id);})
1555 using BooleanInstructionFoldingTestWithMap =
1556 ::testing::TestWithParam<InstructionFoldingCaseWithMap<bool>>;
1558 TEST_P(BooleanInstructionFoldingTestWithMap, Case) {
1559 const auto& tc = GetParam();
1562 std::unique_ptr<ir::IRContext> context =
1563 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
1564 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1565 ASSERT_NE(nullptr, context);
1567 // Fold the instruction to test.
1568 opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
1569 ir::Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
1570 inst = opt::FoldInstructionToConstant(inst, tc.id_map);
1572 // Make sure the instruction folded as expected.
1573 EXPECT_NE(inst, nullptr);
1574 if (inst != nullptr) {
1575 std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
1576 EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
1577 opt::analysis::ConstantManager* const_mrg = context->get_constant_mgr();
1578 const opt::analysis::BoolConstant* result =
1579 const_mrg->GetConstantFromInst(inst)->AsBoolConstant();
1580 EXPECT_NE(result, nullptr);
1581 if (result != nullptr) {
1582 EXPECT_EQ(result->value(), tc.expected_result);
1588 INSTANTIATE_TEST_CASE_P(TestCase, BooleanInstructionFoldingTestWithMap,
1590 // Test case 0: fold %3 = true; %3 || n
1591 InstructionFoldingCaseWithMap<bool>(
1592 Header() + "%main = OpFunction %void None %void_func\n" +
1593 "%main_lab = OpLabel\n" +
1594 "%n = OpVariable %_ptr_bool Function\n" +
1595 "%load = OpLoad %bool %n\n" +
1596 "%3 = OpCopyObject %bool %true\n" +
1597 "%2 = OpLogicalOr %bool %3 %load\n" +
1600 2, true, [](uint32_t id) {return (id == 3 ? TRUE_ID : id);})
1604 using GeneralInstructionFoldingTest =
1605 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
1607 TEST_P(GeneralInstructionFoldingTest, Case) {
1608 const auto& tc = GetParam();
1611 std::unique_ptr<ir::IRContext> context =
1612 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
1613 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
1614 ASSERT_NE(nullptr, context);
1616 // Fold the instruction to test.
1617 opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
1618 ir::Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
1619 std::unique_ptr<ir::Instruction> original_inst(inst->Clone(context.get()));
1620 bool succeeded = opt::FoldInstruction(inst);
1622 // Make sure the instruction folded as expected.
1623 EXPECT_EQ(inst->result_id(), original_inst->result_id());
1624 EXPECT_EQ(inst->type_id(), original_inst->type_id());
1625 EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
1627 EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
1628 EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
1630 EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
1631 for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
1632 EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
1638 INSTANTIATE_TEST_CASE_P(IntegerArithmeticTestCases, GeneralInstructionFoldingTest,
1640 // Test case 0: Don't fold n * m
1641 InstructionFoldingCase<uint32_t>(
1642 Header() + "%main = OpFunction %void None %void_func\n" +
1643 "%main_lab = OpLabel\n" +
1644 "%n = OpVariable %_ptr_int Function\n" +
1645 "%m = OpVariable %_ptr_int Function\n" +
1646 "%load_n = OpLoad %int %n\n" +
1647 "%load_m = OpLoad %int %m\n" +
1648 "%2 = OpIMul %int %load_n %load_m\n" +
1652 // Test case 1: Don't fold n / m (unsigned)
1653 InstructionFoldingCase<uint32_t>(
1654 Header() + "%main = OpFunction %void None %void_func\n" +
1655 "%main_lab = OpLabel\n" +
1656 "%n = OpVariable %_ptr_uint Function\n" +
1657 "%m = OpVariable %_ptr_uint Function\n" +
1658 "%load_n = OpLoad %uint %n\n" +
1659 "%load_m = OpLoad %uint %m\n" +
1660 "%2 = OpUDiv %uint %load_n %load_m\n" +
1664 // Test case 2: Don't fold n / m (signed)
1665 InstructionFoldingCase<uint32_t>(
1666 Header() + "%main = OpFunction %void None %void_func\n" +
1667 "%main_lab = OpLabel\n" +
1668 "%n = OpVariable %_ptr_int Function\n" +
1669 "%m = OpVariable %_ptr_int Function\n" +
1670 "%load_n = OpLoad %int %n\n" +
1671 "%load_m = OpLoad %int %m\n" +
1672 "%2 = OpSDiv %int %load_n %load_m\n" +
1676 // Test case 3: Don't fold n remainder m
1677 InstructionFoldingCase<uint32_t>(
1678 Header() + "%main = OpFunction %void None %void_func\n" +
1679 "%main_lab = OpLabel\n" +
1680 "%n = OpVariable %_ptr_int Function\n" +
1681 "%m = OpVariable %_ptr_int Function\n" +
1682 "%load_n = OpLoad %int %n\n" +
1683 "%load_m = OpLoad %int %m\n" +
1684 "%2 = OpSRem %int %load_n %load_m\n" +
1688 // Test case 4: Don't fold n % m (signed)
1689 InstructionFoldingCase<uint32_t>(
1690 Header() + "%main = OpFunction %void None %void_func\n" +
1691 "%main_lab = OpLabel\n" +
1692 "%n = OpVariable %_ptr_int Function\n" +
1693 "%m = OpVariable %_ptr_int Function\n" +
1694 "%load_n = OpLoad %int %n\n" +
1695 "%load_m = OpLoad %int %m\n" +
1696 "%2 = OpSMod %int %load_n %load_m\n" +
1700 // Test case 5: Don't fold n % m (unsigned)
1701 InstructionFoldingCase<uint32_t>(
1702 Header() + "%main = OpFunction %void None %void_func\n" +
1703 "%main_lab = OpLabel\n" +
1704 "%n = OpVariable %_ptr_uint Function\n" +
1705 "%m = OpVariable %_ptr_uint Function\n" +
1706 "%load_n = OpLoad %uint %n\n" +
1707 "%load_m = OpLoad %uint %m\n" +
1708 "%2 = OpUMod %int %load_n %load_m\n" +
1712 // Test case 6: Don't fold n << m
1713 InstructionFoldingCase<uint32_t>(
1714 Header() + "%main = OpFunction %void None %void_func\n" +
1715 "%main_lab = OpLabel\n" +
1716 "%n = OpVariable %_ptr_uint Function\n" +
1717 "%m = OpVariable %_ptr_uint Function\n" +
1718 "%load_n = OpLoad %uint %n\n" +
1719 "%load_m = OpLoad %uint %m\n" +
1720 "%2 = OpShiftRightLogical %int %load_n %load_m\n" +
1724 // Test case 7: Don't fold n >> m
1725 InstructionFoldingCase<uint32_t>(
1726 Header() + "%main = OpFunction %void None %void_func\n" +
1727 "%main_lab = OpLabel\n" +
1728 "%n = OpVariable %_ptr_uint Function\n" +
1729 "%m = OpVariable %_ptr_uint Function\n" +
1730 "%load_n = OpLoad %uint %n\n" +
1731 "%load_m = OpLoad %uint %m\n" +
1732 "%2 = OpShiftLeftLogical %int %load_n %load_m\n" +
1736 // Test case 8: Don't fold n | m
1737 InstructionFoldingCase<uint32_t>(
1738 Header() + "%main = OpFunction %void None %void_func\n" +
1739 "%main_lab = OpLabel\n" +
1740 "%n = OpVariable %_ptr_uint Function\n" +
1741 "%m = OpVariable %_ptr_uint Function\n" +
1742 "%load_n = OpLoad %uint %n\n" +
1743 "%load_m = OpLoad %uint %m\n" +
1744 "%2 = OpBitwiseOr %int %load_n %load_m\n" +
1748 // Test case 9: Don't fold n & m
1749 InstructionFoldingCase<uint32_t>(
1750 Header() + "%main = OpFunction %void None %void_func\n" +
1751 "%main_lab = OpLabel\n" +
1752 "%n = OpVariable %_ptr_uint Function\n" +
1753 "%m = OpVariable %_ptr_uint Function\n" +
1754 "%load_n = OpLoad %uint %n\n" +
1755 "%load_m = OpLoad %uint %m\n" +
1756 "%2 = OpBitwiseAnd %int %load_n %load_m\n" +
1760 // Test case 10: Don't fold n < m (unsigned)
1761 InstructionFoldingCase<uint32_t>(
1762 Header() + "%main = OpFunction %void None %void_func\n" +
1763 "%main_lab = OpLabel\n" +
1764 "%n = OpVariable %_ptr_uint Function\n" +
1765 "%m = OpVariable %_ptr_uint Function\n" +
1766 "%load_n = OpLoad %uint %n\n" +
1767 "%load_m = OpLoad %uint %m\n" +
1768 "%2 = OpULessThan %bool %load_n %load_m\n" +
1772 // Test case 11: Don't fold n > m (unsigned)
1773 InstructionFoldingCase<uint32_t>(
1774 Header() + "%main = OpFunction %void None %void_func\n" +
1775 "%main_lab = OpLabel\n" +
1776 "%n = OpVariable %_ptr_uint Function\n" +
1777 "%m = OpVariable %_ptr_uint Function\n" +
1778 "%load_n = OpLoad %uint %n\n" +
1779 "%load_m = OpLoad %uint %m\n" +
1780 "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
1784 // Test case 12: Don't fold n <= m (unsigned)
1785 InstructionFoldingCase<uint32_t>(
1786 Header() + "%main = OpFunction %void None %void_func\n" +
1787 "%main_lab = OpLabel\n" +
1788 "%n = OpVariable %_ptr_uint Function\n" +
1789 "%m = OpVariable %_ptr_uint Function\n" +
1790 "%load_n = OpLoad %uint %n\n" +
1791 "%load_m = OpLoad %uint %m\n" +
1792 "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
1796 // Test case 13: Don't fold n >= m (unsigned)
1797 InstructionFoldingCase<uint32_t>(
1798 Header() + "%main = OpFunction %void None %void_func\n" +
1799 "%main_lab = OpLabel\n" +
1800 "%n = OpVariable %_ptr_uint Function\n" +
1801 "%m = OpVariable %_ptr_uint Function\n" +
1802 "%load_n = OpLoad %uint %n\n" +
1803 "%load_m = OpLoad %uint %m\n" +
1804 "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
1808 // Test case 14: Don't fold n < m (signed)
1809 InstructionFoldingCase<uint32_t>(
1810 Header() + "%main = OpFunction %void None %void_func\n" +
1811 "%main_lab = OpLabel\n" +
1812 "%n = OpVariable %_ptr_int Function\n" +
1813 "%m = OpVariable %_ptr_int Function\n" +
1814 "%load_n = OpLoad %int %n\n" +
1815 "%load_m = OpLoad %int %m\n" +
1816 "%2 = OpULessThan %bool %load_n %load_m\n" +
1820 // Test case 15: Don't fold n > m (signed)
1821 InstructionFoldingCase<uint32_t>(
1822 Header() + "%main = OpFunction %void None %void_func\n" +
1823 "%main_lab = OpLabel\n" +
1824 "%n = OpVariable %_ptr_int Function\n" +
1825 "%m = OpVariable %_ptr_int Function\n" +
1826 "%load_n = OpLoad %int %n\n" +
1827 "%load_m = OpLoad %int %m\n" +
1828 "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
1832 // Test case 16: Don't fold n <= m (signed)
1833 InstructionFoldingCase<uint32_t>(
1834 Header() + "%main = OpFunction %void None %void_func\n" +
1835 "%main_lab = OpLabel\n" +
1836 "%n = OpVariable %_ptr_int Function\n" +
1837 "%m = OpVariable %_ptr_int Function\n" +
1838 "%load_n = OpLoad %int %n\n" +
1839 "%load_m = OpLoad %int %m\n" +
1840 "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
1844 // Test case 17: Don't fold n >= m (signed)
1845 InstructionFoldingCase<uint32_t>(
1846 Header() + "%main = OpFunction %void None %void_func\n" +
1847 "%main_lab = OpLabel\n" +
1848 "%n = OpVariable %_ptr_int Function\n" +
1849 "%m = OpVariable %_ptr_int Function\n" +
1850 "%load_n = OpLoad %int %n\n" +
1851 "%load_m = OpLoad %int %m\n" +
1852 "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
1856 // Test case 18: Don't fold n || m
1857 InstructionFoldingCase<uint32_t>(
1858 Header() + "%main = OpFunction %void None %void_func\n" +
1859 "%main_lab = OpLabel\n" +
1860 "%n = OpVariable %_ptr_bool Function\n" +
1861 "%m = OpVariable %_ptr_bool Function\n" +
1862 "%load_n = OpLoad %bool %n\n" +
1863 "%load_m = OpLoad %bool %m\n" +
1864 "%2 = OpLogicalOr %bool %load_n %load_m\n" +
1868 // Test case 19: Don't fold n && m
1869 InstructionFoldingCase<uint32_t>(
1870 Header() + "%main = OpFunction %void None %void_func\n" +
1871 "%main_lab = OpLabel\n" +
1872 "%n = OpVariable %_ptr_bool Function\n" +
1873 "%m = OpVariable %_ptr_bool Function\n" +
1874 "%load_n = OpLoad %bool %n\n" +
1875 "%load_m = OpLoad %bool %m\n" +
1876 "%2 = OpLogicalAnd %bool %load_n %load_m\n" +
1880 // Test case 20: Don't fold n * 3
1881 InstructionFoldingCase<uint32_t>(
1882 Header() + "%main = OpFunction %void None %void_func\n" +
1883 "%main_lab = OpLabel\n" +
1884 "%n = OpVariable %_ptr_int Function\n" +
1885 "%load_n = OpLoad %int %n\n" +
1886 "%2 = OpIMul %int %load_n %int_3\n" +
1890 // Test case 21: Don't fold n / 3 (unsigned)
1891 InstructionFoldingCase<uint32_t>(
1892 Header() + "%main = OpFunction %void None %void_func\n" +
1893 "%main_lab = OpLabel\n" +
1894 "%n = OpVariable %_ptr_uint Function\n" +
1895 "%load_n = OpLoad %uint %n\n" +
1896 "%2 = OpUDiv %uint %load_n %uint_3\n" +
1900 // Test case 22: Don't fold n / 3 (signed)
1901 InstructionFoldingCase<uint32_t>(
1902 Header() + "%main = OpFunction %void None %void_func\n" +
1903 "%main_lab = OpLabel\n" +
1904 "%n = OpVariable %_ptr_int Function\n" +
1905 "%load_n = OpLoad %int %n\n" +
1906 "%2 = OpSDiv %int %load_n %int_3\n" +
1910 // Test case 23: Don't fold n remainder 3
1911 InstructionFoldingCase<uint32_t>(
1912 Header() + "%main = OpFunction %void None %void_func\n" +
1913 "%main_lab = OpLabel\n" +
1914 "%n = OpVariable %_ptr_int Function\n" +
1915 "%load_n = OpLoad %int %n\n" +
1916 "%2 = OpSRem %int %load_n %int_3\n" +
1920 // Test case 24: Don't fold n % 3 (signed)
1921 InstructionFoldingCase<uint32_t>(
1922 Header() + "%main = OpFunction %void None %void_func\n" +
1923 "%main_lab = OpLabel\n" +
1924 "%n = OpVariable %_ptr_int Function\n" +
1925 "%load_n = OpLoad %int %n\n" +
1926 "%2 = OpSMod %int %load_n %int_3\n" +
1930 // Test case 25: Don't fold n % 3 (unsigned)
1931 InstructionFoldingCase<uint32_t>(
1932 Header() + "%main = OpFunction %void None %void_func\n" +
1933 "%main_lab = OpLabel\n" +
1934 "%n = OpVariable %_ptr_uint Function\n" +
1935 "%load_n = OpLoad %uint %n\n" +
1936 "%2 = OpUMod %int %load_n %int_3\n" +
1940 // Test case 26: Don't fold n << 3
1941 InstructionFoldingCase<uint32_t>(
1942 Header() + "%main = OpFunction %void None %void_func\n" +
1943 "%main_lab = OpLabel\n" +
1944 "%n = OpVariable %_ptr_uint Function\n" +
1945 "%load_n = OpLoad %uint %n\n" +
1946 "%2 = OpShiftRightLogical %int %load_n %int_3\n" +
1950 // Test case 27: Don't fold n >> 3
1951 InstructionFoldingCase<uint32_t>(
1952 Header() + "%main = OpFunction %void None %void_func\n" +
1953 "%main_lab = OpLabel\n" +
1954 "%n = OpVariable %_ptr_uint Function\n" +
1955 "%load_n = OpLoad %uint %n\n" +
1956 "%2 = OpShiftLeftLogical %int %load_n %int_3\n" +
1960 // Test case 28: Don't fold n | 3
1961 InstructionFoldingCase<uint32_t>(
1962 Header() + "%main = OpFunction %void None %void_func\n" +
1963 "%main_lab = OpLabel\n" +
1964 "%n = OpVariable %_ptr_uint Function\n" +
1965 "%load_n = OpLoad %uint %n\n" +
1966 "%2 = OpBitwiseOr %int %load_n %int_3\n" +
1970 // Test case 29: Don't fold n & 3
1971 InstructionFoldingCase<uint32_t>(
1972 Header() + "%main = OpFunction %void None %void_func\n" +
1973 "%main_lab = OpLabel\n" +
1974 "%n = OpVariable %_ptr_uint Function\n" +
1975 "%load_n = OpLoad %uint %n\n" +
1976 "%2 = OpBitwiseAnd %uint %load_n %uint_3\n" +
1980 // Test case 30: Don't fold n < 3 (unsigned)
1981 InstructionFoldingCase<uint32_t>(
1982 Header() + "%main = OpFunction %void None %void_func\n" +
1983 "%main_lab = OpLabel\n" +
1984 "%n = OpVariable %_ptr_uint Function\n" +
1985 "%load_n = OpLoad %uint %n\n" +
1986 "%2 = OpULessThan %bool %load_n %uint_3\n" +
1990 // Test case 31: Don't fold n > 3 (unsigned)
1991 InstructionFoldingCase<uint32_t>(
1992 Header() + "%main = OpFunction %void None %void_func\n" +
1993 "%main_lab = OpLabel\n" +
1994 "%n = OpVariable %_ptr_uint Function\n" +
1995 "%load_n = OpLoad %uint %n\n" +
1996 "%2 = OpUGreaterThan %bool %load_n %uint_3\n" +
2000 // Test case 32: Don't fold n <= 3 (unsigned)
2001 InstructionFoldingCase<uint32_t>(
2002 Header() + "%main = OpFunction %void None %void_func\n" +
2003 "%main_lab = OpLabel\n" +
2004 "%n = OpVariable %_ptr_uint Function\n" +
2005 "%load_n = OpLoad %uint %n\n" +
2006 "%2 = OpULessThanEqual %bool %load_n %uint_3\n" +
2010 // Test case 33: Don't fold n >= 3 (unsigned)
2011 InstructionFoldingCase<uint32_t>(
2012 Header() + "%main = OpFunction %void None %void_func\n" +
2013 "%main_lab = OpLabel\n" +
2014 "%n = OpVariable %_ptr_uint Function\n" +
2015 "%load_n = OpLoad %uint %n\n" +
2016 "%2 = OpUGreaterThanEqual %bool %load_n %uint_3\n" +
2020 // Test case 34: Don't fold n < 3 (signed)
2021 InstructionFoldingCase<uint32_t>(
2022 Header() + "%main = OpFunction %void None %void_func\n" +
2023 "%main_lab = OpLabel\n" +
2024 "%n = OpVariable %_ptr_int Function\n" +
2025 "%load_n = OpLoad %int %n\n" +
2026 "%2 = OpULessThan %bool %load_n %int_3\n" +
2030 // Test case 35: Don't fold n > 3 (signed)
2031 InstructionFoldingCase<uint32_t>(
2032 Header() + "%main = OpFunction %void None %void_func\n" +
2033 "%main_lab = OpLabel\n" +
2034 "%n = OpVariable %_ptr_int Function\n" +
2035 "%load_n = OpLoad %int %n\n" +
2036 "%2 = OpUGreaterThan %bool %load_n %int_3\n" +
2040 // Test case 36: Don't fold n <= 3 (signed)
2041 InstructionFoldingCase<uint32_t>(
2042 Header() + "%main = OpFunction %void None %void_func\n" +
2043 "%main_lab = OpLabel\n" +
2044 "%n = OpVariable %_ptr_int Function\n" +
2045 "%load_n = OpLoad %int %n\n" +
2046 "%2 = OpULessThanEqual %bool %load_n %int_3\n" +
2050 // Test case 37: Don't fold n >= 3 (signed)
2051 InstructionFoldingCase<uint32_t>(
2052 Header() + "%main = OpFunction %void None %void_func\n" +
2053 "%main_lab = OpLabel\n" +
2054 "%n = OpVariable %_ptr_int Function\n" +
2055 "%load_n = OpLoad %int %n\n" +
2056 "%2 = OpUGreaterThanEqual %bool %load_n %int_3\n" +
2060 // Test case 38: Don't fold 0 + 3 (long), bad length
2061 InstructionFoldingCase<uint32_t>(
2062 Header() + "%main = OpFunction %void None %void_func\n" +
2063 "%main_lab = OpLabel\n" +
2064 "%2 = OpIAdd %long %long_0 %long_3\n" +
2068 // Test case 39: Don't fold 0 + 3 (short), bad length
2069 InstructionFoldingCase<uint32_t>(
2070 Header() + "%main = OpFunction %void None %void_func\n" +
2071 "%main_lab = OpLabel\n" +
2072 "%2 = OpIAdd %short %short_0 %short_3\n" +
2076 // Test case 40: fold 1*n
2077 InstructionFoldingCase<uint32_t>(
2078 Header() + "%main = OpFunction %void None %void_func\n" +
2079 "%main_lab = OpLabel\n" +
2080 "%n = OpVariable %_ptr_int Function\n" +
2081 "%3 = OpLoad %int %n\n" +
2082 "%2 = OpIMul %int %int_1 %3\n" +
2086 // Test case 41: fold n*1
2087 InstructionFoldingCase<uint32_t>(
2088 Header() + "%main = OpFunction %void None %void_func\n" +
2089 "%main_lab = OpLabel\n" +
2090 "%n = OpVariable %_ptr_int Function\n" +
2091 "%3 = OpLoad %int %n\n" +
2092 "%2 = OpIMul %int %3 %int_1\n" +
2098 INSTANTIATE_TEST_CASE_P(CompositeExtractFoldingTest, GeneralInstructionFoldingTest,
2100 // Test case 0: fold Insert feeding extract
2101 InstructionFoldingCase<uint32_t>(
2102 Header() + "%main = OpFunction %void None %void_func\n" +
2103 "%main_lab = OpLabel\n" +
2104 "%n = OpVariable %_ptr_int Function\n" +
2105 "%2 = OpLoad %int %n\n" +
2106 "%3 = OpCompositeInsert %v4int %2 %v4int_0_0_0_0 0\n" +
2107 "%4 = OpCompositeInsert %v4int %int_1 %3 1\n" +
2108 "%5 = OpCompositeInsert %v4int %int_1 %4 2\n" +
2109 "%6 = OpCompositeInsert %v4int %int_1 %5 3\n" +
2110 "%7 = OpCompositeExtract %int %6 0\n" +
2114 // Test case 1: fold Composite construct feeding extract (position 0)
2115 InstructionFoldingCase<uint32_t>(
2116 Header() + "%main = OpFunction %void None %void_func\n" +
2117 "%main_lab = OpLabel\n" +
2118 "%n = OpVariable %_ptr_int Function\n" +
2119 "%2 = OpLoad %int %n\n" +
2120 "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %int_0\n" +
2121 "%4 = OpCompositeExtract %int %3 0\n" +
2125 // Test case 2: fold Composite construct feeding extract (position 3)
2126 InstructionFoldingCase<uint32_t>(
2127 Header() + "%main = OpFunction %void None %void_func\n" +
2128 "%main_lab = OpLabel\n" +
2129 "%n = OpVariable %_ptr_int Function\n" +
2130 "%2 = OpLoad %int %n\n" +
2131 "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %100\n" +
2132 "%4 = OpCompositeExtract %int %3 3\n" +
2136 // Test case 3: fold Composite construct with vectors feeding extract (scalar element)
2137 InstructionFoldingCase<uint32_t>(
2138 Header() + "%main = OpFunction %void None %void_func\n" +
2139 "%main_lab = OpLabel\n" +
2140 "%n = OpVariable %_ptr_int Function\n" +
2141 "%2 = OpLoad %int %n\n" +
2142 "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
2143 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
2144 "%5 = OpCompositeExtract %int %4 3\n" +
2148 // Test case 4: fold Composite construct with vectors feeding extract (start of vector element)
2149 InstructionFoldingCase<uint32_t>(
2150 Header() + "%main = OpFunction %void None %void_func\n" +
2151 "%main_lab = OpLabel\n" +
2152 "%n = OpVariable %_ptr_int Function\n" +
2153 "%2 = OpLoad %int %n\n" +
2154 "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
2155 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
2156 "%5 = OpCompositeExtract %int %4 0\n" +
2160 // Test case 5: fold Composite construct with vectors feeding extract (middle of vector element)
2161 InstructionFoldingCase<uint32_t>(
2162 Header() + "%main = OpFunction %void None %void_func\n" +
2163 "%main_lab = OpLabel\n" +
2164 "%n = OpVariable %_ptr_int Function\n" +
2165 "%2 = OpLoad %int %n\n" +
2166 "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
2167 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
2168 "%5 = OpCompositeExtract %int %4 1\n" +
2172 // Test case 6: fold Composite construct with multiple indices.
2173 InstructionFoldingCase<uint32_t>(
2174 Header() + "%main = OpFunction %void None %void_func\n" +
2175 "%main_lab = OpLabel\n" +
2176 "%n = OpVariable %_ptr_int Function\n" +
2177 "%2 = OpLoad %int %n\n" +
2178 "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
2179 "%4 = OpCompositeConstruct %struct_v2int_int_int %3 %int_0 %100\n" +
2180 "%5 = OpCompositeExtract %int %4 0 1\n" +
2184 // Test case 7: fold constant extract.
2185 InstructionFoldingCase<uint32_t>(
2186 Header() + "%main = OpFunction %void None %void_func\n" +
2187 "%main_lab = OpLabel\n" +
2188 "%2 = OpCompositeExtract %int %102 1\n" +
2192 // Test case 8: constant struct has OpUndef
2193 InstructionFoldingCase<uint32_t>(
2194 Header() + "%main = OpFunction %void None %void_func\n" +
2195 "%main_lab = OpLabel\n" +
2196 "%2 = OpCompositeExtract %int %struct_undef_0_0 0 1\n" +
2200 // Test case 9: Extracting a member of element inserted via Insert
2201 InstructionFoldingCase<uint32_t>(
2202 Header() + "%main = OpFunction %void None %void_func\n" +
2203 "%main_lab = OpLabel\n" +
2204 "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
2205 "%2 = OpLoad %struct_v2int_int_int %n\n" +
2206 "%3 = OpCompositeInsert %struct_v2int_int_int %102 %2 0\n" +
2207 "%4 = OpCompositeExtract %int %3 0 1\n" +
2211 // Test case 10: Extracting a element that is partially changed by Insert. (Don't fold)
2212 InstructionFoldingCase<uint32_t>(
2213 Header() + "%main = OpFunction %void None %void_func\n" +
2214 "%main_lab = OpLabel\n" +
2215 "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
2216 "%2 = OpLoad %struct_v2int_int_int %n\n" +
2217 "%3 = OpCompositeInsert %struct_v2int_int_int %int_0 %2 0 1\n" +
2218 "%4 = OpCompositeExtract %v2int %3 0\n" +
2222 // Test case 11: Extracting from result of vector shuffle (first input)
2223 InstructionFoldingCase<uint32_t>(
2224 Header() + "%main = OpFunction %void None %void_func\n" +
2225 "%main_lab = OpLabel\n" +
2226 "%n = OpVariable %_ptr_v2int Function\n" +
2227 "%2 = OpLoad %v2int %n\n" +
2228 "%3 = OpVectorShuffle %v2int %102 %2 3 0\n" +
2229 "%4 = OpCompositeExtract %int %3 1\n" +
2233 // Test case 12: Extracting from result of vector shuffle (second input)
2234 InstructionFoldingCase<uint32_t>(
2235 Header() + "%main = OpFunction %void None %void_func\n" +
2236 "%main_lab = OpLabel\n" +
2237 "%n = OpVariable %_ptr_v2int Function\n" +
2238 "%2 = OpLoad %v2int %n\n" +
2239 "%3 = OpVectorShuffle %v2int %2 %102 2 0\n" +
2240 "%4 = OpCompositeExtract %int %3 0\n" +
2246 INSTANTIATE_TEST_CASE_P(CompositeConstructFoldingTest, GeneralInstructionFoldingTest,
2248 // Test case 0: fold Extracts feeding construct
2249 InstructionFoldingCase<uint32_t>(
2250 Header() + "%main = OpFunction %void None %void_func\n" +
2251 "%main_lab = OpLabel\n" +
2252 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
2253 "%3 = OpCompositeExtract %int %2 0\n" +
2254 "%4 = OpCompositeExtract %int %2 1\n" +
2255 "%5 = OpCompositeExtract %int %2 2\n" +
2256 "%6 = OpCompositeExtract %int %2 3\n" +
2257 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
2261 // Test case 1: Don't fold Extracts feeding construct (Different source)
2262 InstructionFoldingCase<uint32_t>(
2263 Header() + "%main = OpFunction %void None %void_func\n" +
2264 "%main_lab = OpLabel\n" +
2265 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
2266 "%3 = OpCompositeExtract %int %2 0\n" +
2267 "%4 = OpCompositeExtract %int %2 1\n" +
2268 "%5 = OpCompositeExtract %int %2 2\n" +
2269 "%6 = OpCompositeExtract %int %v4int_0_0_0_0 3\n" +
2270 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
2274 // Test case 2: Don't fold Extracts feeding construct (bad indices)
2275 InstructionFoldingCase<uint32_t>(
2276 Header() + "%main = OpFunction %void None %void_func\n" +
2277 "%main_lab = OpLabel\n" +
2278 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
2279 "%3 = OpCompositeExtract %int %2 0\n" +
2280 "%4 = OpCompositeExtract %int %2 0\n" +
2281 "%5 = OpCompositeExtract %int %2 2\n" +
2282 "%6 = OpCompositeExtract %int %2 3\n" +
2283 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
2287 // Test case 3: Don't fold Extracts feeding construct (different type)
2288 InstructionFoldingCase<uint32_t>(
2289 Header() + "%main = OpFunction %void None %void_func\n" +
2290 "%main_lab = OpLabel\n" +
2291 "%2 = OpCopyObject %struct_v2int_int_int %struct_v2int_int_int_null\n" +
2292 "%3 = OpCompositeExtract %v2int %2 0\n" +
2293 "%4 = OpCompositeExtract %int %2 1\n" +
2294 "%5 = OpCompositeExtract %int %2 2\n" +
2295 "%7 = OpCompositeConstruct %v4int %3 %4 %5\n" +
2299 // Test case 4: Fold construct with constants to constant.
2300 InstructionFoldingCase<uint32_t>(
2301 Header() + "%main = OpFunction %void None %void_func\n" +
2302 "%main_lab = OpLabel\n" +
2303 "%2 = OpCompositeConstruct %v2int %103 %103\n" +
2309 INSTANTIATE_TEST_CASE_P(PhiFoldingTest, GeneralInstructionFoldingTest,
2311 // Test case 0: Fold phi with the same values for all edges.
2312 InstructionFoldingCase<uint32_t>(
2313 Header() + "%main = OpFunction %void None %void_func\n" +
2314 "%main_lab = OpLabel\n" +
2315 " OpBranchConditional %true %l1 %l2\n" +
2317 " OpBranch %merge_lab\n" +
2319 " OpBranch %merge_lab\n" +
2320 "%merge_lab = OpLabel\n" +
2321 "%2 = OpPhi %int %100 %l1 %100 %l2\n" +
2325 // Test case 1: Fold phi in pass through loop.
2326 InstructionFoldingCase<uint32_t>(
2327 Header() + "%main = OpFunction %void None %void_func\n" +
2328 "%main_lab = OpLabel\n" +
2331 "%2 = OpPhi %int %100 %main_lab %2 %l1\n" +
2332 " OpBranchConditional %true %l1 %merge_lab\n" +
2333 "%merge_lab = OpLabel\n" +
2337 // Test case 2: Don't Fold phi because of different values.
2338 InstructionFoldingCase<uint32_t>(
2339 Header() + "%main = OpFunction %void None %void_func\n" +
2340 "%main_lab = OpLabel\n" +
2343 "%2 = OpPhi %int %int_0 %main_lab %int_3 %l1\n" +
2344 " OpBranchConditional %true %l1 %merge_lab\n" +
2345 "%merge_lab = OpLabel\n" +
2351 INSTANTIATE_TEST_CASE_P(FloatRedundantFoldingTest, GeneralInstructionFoldingTest,
2353 // Test case 0: Don't fold n + 1.0
2354 InstructionFoldingCase<uint32_t>(
2355 Header() + "%main = OpFunction %void None %void_func\n" +
2356 "%main_lab = OpLabel\n" +
2357 "%n = OpVariable %_ptr_float Function\n" +
2358 "%3 = OpLoad %float %n\n" +
2359 "%2 = OpFAdd %float %3 %float_2\n" +
2363 // Test case 1: Don't fold n - 1.0
2364 InstructionFoldingCase<uint32_t>(
2365 Header() + "%main = OpFunction %void None %void_func\n" +
2366 "%main_lab = OpLabel\n" +
2367 "%n = OpVariable %_ptr_float Function\n" +
2368 "%3 = OpLoad %float %n\n" +
2369 "%2 = OpFSub %float %3 %float_2\n" +
2373 // Test case 2: Don't fold n * 2.0
2374 InstructionFoldingCase<uint32_t>(
2375 Header() + "%main = OpFunction %void None %void_func\n" +
2376 "%main_lab = OpLabel\n" +
2377 "%n = OpVariable %_ptr_float Function\n" +
2378 "%3 = OpLoad %float %n\n" +
2379 "%2 = OpFMul %float %3 %float_2\n" +
2383 // Test case 3: Fold n + 0.0
2384 InstructionFoldingCase<uint32_t>(
2385 Header() + "%main = OpFunction %void None %void_func\n" +
2386 "%main_lab = OpLabel\n" +
2387 "%n = OpVariable %_ptr_float Function\n" +
2388 "%3 = OpLoad %float %n\n" +
2389 "%2 = OpFAdd %float %3 %float_0\n" +
2393 // Test case 4: Fold 0.0 + n
2394 InstructionFoldingCase<uint32_t>(
2395 Header() + "%main = OpFunction %void None %void_func\n" +
2396 "%main_lab = OpLabel\n" +
2397 "%n = OpVariable %_ptr_float Function\n" +
2398 "%3 = OpLoad %float %n\n" +
2399 "%2 = OpFAdd %float %float_0 %3\n" +
2403 // Test case 5: Fold n - 0.0
2404 InstructionFoldingCase<uint32_t>(
2405 Header() + "%main = OpFunction %void None %void_func\n" +
2406 "%main_lab = OpLabel\n" +
2407 "%n = OpVariable %_ptr_float Function\n" +
2408 "%3 = OpLoad %float %n\n" +
2409 "%2 = OpFSub %float %3 %float_0\n" +
2413 // Test case 6: Fold n * 1.0
2414 InstructionFoldingCase<uint32_t>(
2415 Header() + "%main = OpFunction %void None %void_func\n" +
2416 "%main_lab = OpLabel\n" +
2417 "%n = OpVariable %_ptr_float Function\n" +
2418 "%3 = OpLoad %float %n\n" +
2419 "%2 = OpFMul %float %3 %float_1\n" +
2423 // Test case 7: Fold 1.0 * n
2424 InstructionFoldingCase<uint32_t>(
2425 Header() + "%main = OpFunction %void None %void_func\n" +
2426 "%main_lab = OpLabel\n" +
2427 "%n = OpVariable %_ptr_float Function\n" +
2428 "%3 = OpLoad %float %n\n" +
2429 "%2 = OpFMul %float %float_1 %3\n" +
2433 // Test case 8: Fold n / 1.0
2434 InstructionFoldingCase<uint32_t>(
2435 Header() + "%main = OpFunction %void None %void_func\n" +
2436 "%main_lab = OpLabel\n" +
2437 "%n = OpVariable %_ptr_float Function\n" +
2438 "%3 = OpLoad %float %n\n" +
2439 "%2 = OpFDiv %float %3 %float_1\n" +
2443 // Test case 9: Fold n * 0.0
2444 InstructionFoldingCase<uint32_t>(
2445 Header() + "%main = OpFunction %void None %void_func\n" +
2446 "%main_lab = OpLabel\n" +
2447 "%n = OpVariable %_ptr_float Function\n" +
2448 "%3 = OpLoad %float %n\n" +
2449 "%2 = OpFMul %float %3 %104\n" +
2453 // Test case 10: Fold 0.0 * n
2454 InstructionFoldingCase<uint32_t>(
2455 Header() + "%main = OpFunction %void None %void_func\n" +
2456 "%main_lab = OpLabel\n" +
2457 "%n = OpVariable %_ptr_float Function\n" +
2458 "%3 = OpLoad %float %n\n" +
2459 "%2 = OpFMul %float %104 %3\n" +
2463 // Test case 11: Fold 0.0 / n
2464 InstructionFoldingCase<uint32_t>(
2465 Header() + "%main = OpFunction %void None %void_func\n" +
2466 "%main_lab = OpLabel\n" +
2467 "%n = OpVariable %_ptr_float Function\n" +
2468 "%3 = OpLoad %float %n\n" +
2469 "%2 = OpFDiv %float %104 %3\n" +
2473 // Test case 12: Don't fold mix(a, b, 2.0)
2474 InstructionFoldingCase<uint32_t>(
2475 Header() + "%main = OpFunction %void None %void_func\n" +
2476 "%main_lab = OpLabel\n" +
2477 "%a = OpVariable %_ptr_float Function\n" +
2478 "%b = OpVariable %_ptr_float Function\n" +
2479 "%3 = OpLoad %float %a\n" +
2480 "%4 = OpLoad %float %b\n" +
2481 "%2 = OpExtInst %float %1 FMix %3 %4 %float_2\n" +
2485 // Test case 13: Fold mix(a, b, 0.0)
2486 InstructionFoldingCase<uint32_t>(
2487 Header() + "%main = OpFunction %void None %void_func\n" +
2488 "%main_lab = OpLabel\n" +
2489 "%a = OpVariable %_ptr_float Function\n" +
2490 "%b = OpVariable %_ptr_float Function\n" +
2491 "%3 = OpLoad %float %a\n" +
2492 "%4 = OpLoad %float %b\n" +
2493 "%2 = OpExtInst %float %1 FMix %3 %4 %float_0\n" +
2497 // Test case 14: Fold mix(a, b, 1.0)
2498 InstructionFoldingCase<uint32_t>(
2499 Header() + "%main = OpFunction %void None %void_func\n" +
2500 "%main_lab = OpLabel\n" +
2501 "%a = OpVariable %_ptr_float Function\n" +
2502 "%b = OpVariable %_ptr_float Function\n" +
2503 "%3 = OpLoad %float %a\n" +
2504 "%4 = OpLoad %float %b\n" +
2505 "%2 = OpExtInst %float %1 FMix %3 %4 %float_1\n" +
2509 // Test case 15: Fold vector fadd with null
2510 InstructionFoldingCase<uint32_t>(
2511 Header() + "%main = OpFunction %void None %void_func\n" +
2512 "%main_lab = OpLabel\n" +
2513 "%a = OpVariable %_ptr_v2float Function\n" +
2514 "%2 = OpLoad %v2float %a\n" +
2515 "%3 = OpFAdd %v2float %2 %v2float_null\n" +
2519 // Test case 16: Fold vector fadd with null
2520 InstructionFoldingCase<uint32_t>(
2521 Header() + "%main = OpFunction %void None %void_func\n" +
2522 "%main_lab = OpLabel\n" +
2523 "%a = OpVariable %_ptr_v2float Function\n" +
2524 "%2 = OpLoad %v2float %a\n" +
2525 "%3 = OpFAdd %v2float %v2float_null %2\n" +
2529 // Test case 15: Fold vector fsub with null
2530 InstructionFoldingCase<uint32_t>(
2531 Header() + "%main = OpFunction %void None %void_func\n" +
2532 "%main_lab = OpLabel\n" +
2533 "%a = OpVariable %_ptr_v2float Function\n" +
2534 "%2 = OpLoad %v2float %a\n" +
2535 "%3 = OpFSub %v2float %2 %v2float_null\n" +
2539 // Test case 16: Fold 0.0(half) * n
2540 InstructionFoldingCase<uint32_t>(
2541 Header() + "%main = OpFunction %void None %void_func\n" +
2542 "%main_lab = OpLabel\n" +
2543 "%n = OpVariable %_ptr_half Function\n" +
2544 "%3 = OpLoad %half %n\n" +
2545 "%2 = OpFMul %half %108 %3\n" +
2549 // Test case 17: Don't fold 1.0(half) * n
2550 InstructionFoldingCase<uint32_t>(
2551 Header() + "%main = OpFunction %void None %void_func\n" +
2552 "%main_lab = OpLabel\n" +
2553 "%n = OpVariable %_ptr_half Function\n" +
2554 "%3 = OpLoad %half %n\n" +
2555 "%2 = OpFMul %half %half_1 %3\n" +
2559 // Test case 18: Don't fold 1.0 * 1.0 (half)
2560 InstructionFoldingCase<uint32_t>(
2561 Header() + "%main = OpFunction %void None %void_func\n" +
2562 "%main_lab = OpLabel\n" +
2563 "%2 = OpFMul %half %half_1 %half_1\n" +
2569 INSTANTIATE_TEST_CASE_P(DoubleRedundantFoldingTest, GeneralInstructionFoldingTest,
2571 // Test case 0: Don't fold n + 1.0
2572 InstructionFoldingCase<uint32_t>(
2573 Header() + "%main = OpFunction %void None %void_func\n" +
2574 "%main_lab = OpLabel\n" +
2575 "%n = OpVariable %_ptr_double Function\n" +
2576 "%3 = OpLoad %double %n\n" +
2577 "%2 = OpFAdd %double %3 %double_2\n" +
2581 // Test case 1: Don't fold n - 1.0
2582 InstructionFoldingCase<uint32_t>(
2583 Header() + "%main = OpFunction %void None %void_func\n" +
2584 "%main_lab = OpLabel\n" +
2585 "%n = OpVariable %_ptr_double Function\n" +
2586 "%3 = OpLoad %double %n\n" +
2587 "%2 = OpFSub %double %3 %double_2\n" +
2591 // Test case 2: Don't fold n * 2.0
2592 InstructionFoldingCase<uint32_t>(
2593 Header() + "%main = OpFunction %void None %void_func\n" +
2594 "%main_lab = OpLabel\n" +
2595 "%n = OpVariable %_ptr_double Function\n" +
2596 "%3 = OpLoad %double %n\n" +
2597 "%2 = OpFMul %double %3 %double_2\n" +
2601 // Test case 3: Fold n + 0.0
2602 InstructionFoldingCase<uint32_t>(
2603 Header() + "%main = OpFunction %void None %void_func\n" +
2604 "%main_lab = OpLabel\n" +
2605 "%n = OpVariable %_ptr_double Function\n" +
2606 "%3 = OpLoad %double %n\n" +
2607 "%2 = OpFAdd %double %3 %double_0\n" +
2611 // Test case 4: Fold 0.0 + n
2612 InstructionFoldingCase<uint32_t>(
2613 Header() + "%main = OpFunction %void None %void_func\n" +
2614 "%main_lab = OpLabel\n" +
2615 "%n = OpVariable %_ptr_double Function\n" +
2616 "%3 = OpLoad %double %n\n" +
2617 "%2 = OpFAdd %double %double_0 %3\n" +
2621 // Test case 5: Fold n - 0.0
2622 InstructionFoldingCase<uint32_t>(
2623 Header() + "%main = OpFunction %void None %void_func\n" +
2624 "%main_lab = OpLabel\n" +
2625 "%n = OpVariable %_ptr_double Function\n" +
2626 "%3 = OpLoad %double %n\n" +
2627 "%2 = OpFSub %double %3 %double_0\n" +
2631 // Test case 6: Fold n * 1.0
2632 InstructionFoldingCase<uint32_t>(
2633 Header() + "%main = OpFunction %void None %void_func\n" +
2634 "%main_lab = OpLabel\n" +
2635 "%n = OpVariable %_ptr_double Function\n" +
2636 "%3 = OpLoad %double %n\n" +
2637 "%2 = OpFMul %double %3 %double_1\n" +
2641 // Test case 7: Fold 1.0 * n
2642 InstructionFoldingCase<uint32_t>(
2643 Header() + "%main = OpFunction %void None %void_func\n" +
2644 "%main_lab = OpLabel\n" +
2645 "%n = OpVariable %_ptr_double Function\n" +
2646 "%3 = OpLoad %double %n\n" +
2647 "%2 = OpFMul %double %double_1 %3\n" +
2651 // Test case 8: Fold n / 1.0
2652 InstructionFoldingCase<uint32_t>(
2653 Header() + "%main = OpFunction %void None %void_func\n" +
2654 "%main_lab = OpLabel\n" +
2655 "%n = OpVariable %_ptr_double Function\n" +
2656 "%3 = OpLoad %double %n\n" +
2657 "%2 = OpFDiv %double %3 %double_1\n" +
2661 // Test case 9: Fold n * 0.0
2662 InstructionFoldingCase<uint32_t>(
2663 Header() + "%main = OpFunction %void None %void_func\n" +
2664 "%main_lab = OpLabel\n" +
2665 "%n = OpVariable %_ptr_double Function\n" +
2666 "%3 = OpLoad %double %n\n" +
2667 "%2 = OpFMul %double %3 %105\n" +
2671 // Test case 10: Fold 0.0 * n
2672 InstructionFoldingCase<uint32_t>(
2673 Header() + "%main = OpFunction %void None %void_func\n" +
2674 "%main_lab = OpLabel\n" +
2675 "%n = OpVariable %_ptr_double Function\n" +
2676 "%3 = OpLoad %double %n\n" +
2677 "%2 = OpFMul %double %105 %3\n" +
2681 // Test case 11: Fold 0.0 / n
2682 InstructionFoldingCase<uint32_t>(
2683 Header() + "%main = OpFunction %void None %void_func\n" +
2684 "%main_lab = OpLabel\n" +
2685 "%n = OpVariable %_ptr_double Function\n" +
2686 "%3 = OpLoad %double %n\n" +
2687 "%2 = OpFDiv %double %105 %3\n" +
2691 // Test case 12: Don't fold mix(a, b, 2.0)
2692 InstructionFoldingCase<uint32_t>(
2693 Header() + "%main = OpFunction %void None %void_func\n" +
2694 "%main_lab = OpLabel\n" +
2695 "%a = OpVariable %_ptr_double Function\n" +
2696 "%b = OpVariable %_ptr_double Function\n" +
2697 "%3 = OpLoad %double %a\n" +
2698 "%4 = OpLoad %double %b\n" +
2699 "%2 = OpExtInst %double %1 FMix %3 %4 %double_2\n" +
2703 // Test case 13: Fold mix(a, b, 0.0)
2704 InstructionFoldingCase<uint32_t>(
2705 Header() + "%main = OpFunction %void None %void_func\n" +
2706 "%main_lab = OpLabel\n" +
2707 "%a = OpVariable %_ptr_double Function\n" +
2708 "%b = OpVariable %_ptr_double Function\n" +
2709 "%3 = OpLoad %double %a\n" +
2710 "%4 = OpLoad %double %b\n" +
2711 "%2 = OpExtInst %double %1 FMix %3 %4 %double_0\n" +
2715 // Test case 14: Fold mix(a, b, 1.0)
2716 InstructionFoldingCase<uint32_t>(
2717 Header() + "%main = OpFunction %void None %void_func\n" +
2718 "%main_lab = OpLabel\n" +
2719 "%a = OpVariable %_ptr_double Function\n" +
2720 "%b = OpVariable %_ptr_double Function\n" +
2721 "%3 = OpLoad %double %a\n" +
2722 "%4 = OpLoad %double %b\n" +
2723 "%2 = OpExtInst %double %1 FMix %3 %4 %double_1\n" +
2729 INSTANTIATE_TEST_CASE_P(FloatVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
2731 // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
2732 InstructionFoldingCase<uint32_t>(
2733 Header() + "%main = OpFunction %void None %void_func\n" +
2734 "%main_lab = OpLabel\n" +
2735 "%n = OpVariable %_ptr_v4float Function\n" +
2736 "%3 = OpLoad %v4float %n\n" +
2737 "%2 = OpFMul %v4float %3 %v4float_0_0_0_1\n" +
2741 // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
2742 InstructionFoldingCase<uint32_t>(
2743 Header() + "%main = OpFunction %void None %void_func\n" +
2744 "%main_lab = OpLabel\n" +
2745 "%n = OpVariable %_ptr_v4float Function\n" +
2746 "%3 = OpLoad %v4float %n\n" +
2747 "%2 = OpFMul %v4float %3 %106\n" +
2751 // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
2752 InstructionFoldingCase<uint32_t>(
2753 Header() + "%main = OpFunction %void None %void_func\n" +
2754 "%main_lab = OpLabel\n" +
2755 "%n = OpVariable %_ptr_v4float Function\n" +
2756 "%3 = OpLoad %v4float %n\n" +
2757 "%2 = OpFMul %v4float %3 %v4float_1_1_1_1\n" +
2763 INSTANTIATE_TEST_CASE_P(DoubleVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
2765 // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
2766 InstructionFoldingCase<uint32_t>(
2767 Header() + "%main = OpFunction %void None %void_func\n" +
2768 "%main_lab = OpLabel\n" +
2769 "%n = OpVariable %_ptr_v4double Function\n" +
2770 "%3 = OpLoad %v4double %n\n" +
2771 "%2 = OpFMul %v4double %3 %v4double_0_0_0_1\n" +
2775 // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
2776 InstructionFoldingCase<uint32_t>(
2777 Header() + "%main = OpFunction %void None %void_func\n" +
2778 "%main_lab = OpLabel\n" +
2779 "%n = OpVariable %_ptr_v4double Function\n" +
2780 "%3 = OpLoad %v4double %n\n" +
2781 "%2 = OpFMul %v4double %3 %106\n" +
2785 // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
2786 InstructionFoldingCase<uint32_t>(
2787 Header() + "%main = OpFunction %void None %void_func\n" +
2788 "%main_lab = OpLabel\n" +
2789 "%n = OpVariable %_ptr_v4double Function\n" +
2790 "%3 = OpLoad %v4double %n\n" +
2791 "%2 = OpFMul %v4double %3 %v4double_1_1_1_1\n" +
2797 INSTANTIATE_TEST_CASE_P(FToIConstantFoldingTest, IntegerInstructionFoldingTest,
2799 // Test case 0: Fold int(3.0)
2800 InstructionFoldingCase<uint32_t>(
2801 Header() + "%main = OpFunction %void None %void_func\n" +
2802 "%main_lab = OpLabel\n" +
2803 "%2 = OpConvertFToS %int %float_3\n" +
2807 // Test case 1: Fold uint(3.0)
2808 InstructionFoldingCase<uint32_t>(
2809 Header() + "%main = OpFunction %void None %void_func\n" +
2810 "%main_lab = OpLabel\n" +
2811 "%2 = OpConvertFToU %int %float_3\n" +
2817 INSTANTIATE_TEST_CASE_P(IToFConstantFoldingTest, FloatInstructionFoldingTest,
2819 // Test case 0: Fold float(3)
2820 InstructionFoldingCase<float>(
2821 Header() + "%main = OpFunction %void None %void_func\n" +
2822 "%main_lab = OpLabel\n" +
2823 "%2 = OpConvertSToF %float %int_3\n" +
2827 // Test case 1: Fold float(3u)
2828 InstructionFoldingCase<float>(
2829 Header() + "%main = OpFunction %void None %void_func\n" +
2830 "%main_lab = OpLabel\n" +
2831 "%2 = OpConvertUToF %float %uint_3\n" +
2838 using ToNegateFoldingTest =
2839 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
2841 TEST_P(ToNegateFoldingTest, Case) {
2842 const auto& tc = GetParam();
2845 std::unique_ptr<ir::IRContext> context =
2846 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
2847 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2848 ASSERT_NE(nullptr, context);
2850 // Fold the instruction to test.
2851 opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
2852 ir::Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
2853 std::unique_ptr<ir::Instruction> original_inst(inst->Clone(context.get()));
2854 bool succeeded = opt::FoldInstruction(inst);
2856 // Make sure the instruction folded as expected.
2857 EXPECT_EQ(inst->result_id(), original_inst->result_id());
2858 EXPECT_EQ(inst->type_id(), original_inst->type_id());
2859 EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
2861 EXPECT_EQ(inst->opcode(), SpvOpFNegate);
2862 EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
2864 EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
2865 for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
2866 EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
2872 INSTANTIATE_TEST_CASE_P(FloatRedundantSubFoldingTest, ToNegateFoldingTest,
2874 // Test case 0: Don't fold 1.0 - n
2875 InstructionFoldingCase<uint32_t>(
2876 Header() + "%main = OpFunction %void None %void_func\n" +
2877 "%main_lab = OpLabel\n" +
2878 "%n = OpVariable %_ptr_float Function\n" +
2879 "%3 = OpLoad %float %n\n" +
2880 "%2 = OpFSub %float %float_1 %3\n" +
2884 // Test case 1: Fold 0.0 - n
2885 InstructionFoldingCase<uint32_t>(
2886 Header() + "%main = OpFunction %void None %void_func\n" +
2887 "%main_lab = OpLabel\n" +
2888 "%n = OpVariable %_ptr_float Function\n" +
2889 "%3 = OpLoad %float %n\n" +
2890 "%2 = OpFSub %float %float_0 %3\n" +
2894 // Test case 2: Don't fold (0,0,0,1) - n
2895 InstructionFoldingCase<uint32_t>(
2896 Header() + "%main = OpFunction %void None %void_func\n" +
2897 "%main_lab = OpLabel\n" +
2898 "%n = OpVariable %_ptr_v4float Function\n" +
2899 "%3 = OpLoad %v4float %n\n" +
2900 "%2 = OpFSub %v4float %v4float_0_0_0_1 %3\n" +
2904 // Test case 3: Fold (0,0,0,0) - n
2905 InstructionFoldingCase<uint32_t>(
2906 Header() + "%main = OpFunction %void None %void_func\n" +
2907 "%main_lab = OpLabel\n" +
2908 "%n = OpVariable %_ptr_v4float Function\n" +
2909 "%3 = OpLoad %v4float %n\n" +
2910 "%2 = OpFSub %v4float %v4float_0_0_0_0 %3\n" +
2916 INSTANTIATE_TEST_CASE_P(DoubleRedundantSubFoldingTest, ToNegateFoldingTest,
2918 // Test case 0: Don't fold 1.0 - n
2919 InstructionFoldingCase<uint32_t>(
2920 Header() + "%main = OpFunction %void None %void_func\n" +
2921 "%main_lab = OpLabel\n" +
2922 "%n = OpVariable %_ptr_double Function\n" +
2923 "%3 = OpLoad %double %n\n" +
2924 "%2 = OpFSub %double %double_1 %3\n" +
2928 // Test case 1: Fold 0.0 - n
2929 InstructionFoldingCase<uint32_t>(
2930 Header() + "%main = OpFunction %void None %void_func\n" +
2931 "%main_lab = OpLabel\n" +
2932 "%n = OpVariable %_ptr_double Function\n" +
2933 "%3 = OpLoad %double %n\n" +
2934 "%2 = OpFSub %double %double_0 %3\n" +
2938 // Test case 2: Don't fold (0,0,0,1) - n
2939 InstructionFoldingCase<uint32_t>(
2940 Header() + "%main = OpFunction %void None %void_func\n" +
2941 "%main_lab = OpLabel\n" +
2942 "%n = OpVariable %_ptr_v4double Function\n" +
2943 "%3 = OpLoad %v4double %n\n" +
2944 "%2 = OpFSub %v4double %v4double_0_0_0_1 %3\n" +
2948 // Test case 3: Fold (0,0,0,0) - n
2949 InstructionFoldingCase<uint32_t>(
2950 Header() + "%main = OpFunction %void None %void_func\n" +
2951 "%main_lab = OpLabel\n" +
2952 "%n = OpVariable %_ptr_v4double Function\n" +
2953 "%3 = OpLoad %v4double %n\n" +
2954 "%2 = OpFSub %v4double %v4double_0_0_0_0 %3\n" +
2961 using MatchingInstructionFoldingTest =
2962 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
2964 TEST_P(MatchingInstructionFoldingTest, Case) {
2965 const auto& tc = GetParam();
2968 std::unique_ptr<ir::IRContext> context =
2969 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
2970 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
2971 ASSERT_NE(nullptr, context);
2973 // Fold the instruction to test.
2974 opt::analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
2975 ir::Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
2976 std::unique_ptr<ir::Instruction> original_inst(inst->Clone(context.get()));
2977 bool succeeded = opt::FoldInstruction(inst);
2978 EXPECT_EQ(succeeded, tc.expected_result);
2980 Match(tc.test_body, context.get());
2984 INSTANTIATE_TEST_CASE_P(MergeNegateTest, MatchingInstructionFoldingTest,
2986 // Test case 0: fold consecutive fnegate
2988 InstructionFoldingCase<bool>(
2990 "; CHECK: [[ld:%\\w+]] = OpLoad [[float:%\\w+]]\n" +
2991 "; CHECK: %4 = OpCopyObject [[float]] [[ld]]\n" +
2992 "%main = OpFunction %void None %void_func\n" +
2993 "%main_lab = OpLabel\n" +
2994 "%var = OpVariable %_ptr_float Function\n" +
2995 "%2 = OpLoad %float %var\n" +
2996 "%3 = OpFNegate %float %2\n" +
2997 "%4 = OpFNegate %float %3\n" +
3001 // Test case 1: fold fnegate(fmul with const).
3002 // -(x * 2.0) = x * -2.0
3003 InstructionFoldingCase<bool>(
3005 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3006 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
3007 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3008 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
3009 "%main = OpFunction %void None %void_func\n" +
3010 "%main_lab = OpLabel\n" +
3011 "%var = OpVariable %_ptr_float Function\n" +
3012 "%2 = OpLoad %float %var\n" +
3013 "%3 = OpFMul %float %2 %float_2\n" +
3014 "%4 = OpFNegate %float %3\n" +
3018 // Test case 2: fold fnegate(fmul with const).
3019 // -(2.0 * x) = x * 2.0
3020 InstructionFoldingCase<bool>(
3022 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3023 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
3024 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3025 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
3026 "%main = OpFunction %void None %void_func\n" +
3027 "%main_lab = OpLabel\n" +
3028 "%var = OpVariable %_ptr_float Function\n" +
3029 "%2 = OpLoad %float %var\n" +
3030 "%3 = OpFMul %float %float_2 %2\n" +
3031 "%4 = OpFNegate %float %3\n" +
3035 // Test case 3: fold fnegate(fdiv with const).
3036 // -(x / 2.0) = x * -0.5
3037 InstructionFoldingCase<bool>(
3039 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3040 "; CHECK: [[float_n0p5:%\\w+]] = OpConstant [[float]] -0.5\n" +
3041 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3042 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n0p5]]\n" +
3043 "%main = OpFunction %void None %void_func\n" +
3044 "%main_lab = OpLabel\n" +
3045 "%var = OpVariable %_ptr_float Function\n" +
3046 "%2 = OpLoad %float %var\n" +
3047 "%3 = OpFDiv %float %2 %float_2\n" +
3048 "%4 = OpFNegate %float %3\n" +
3052 // Test case 4: fold fnegate(fdiv with const).
3053 // -(2.0 / x) = -2.0 / x
3054 InstructionFoldingCase<bool>(
3056 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3057 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
3058 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3059 "; CHECK: %4 = OpFDiv [[float]] [[float_n2]] [[ld]]\n" +
3060 "%main = OpFunction %void None %void_func\n" +
3061 "%main_lab = OpLabel\n" +
3062 "%var = OpVariable %_ptr_float Function\n" +
3063 "%2 = OpLoad %float %var\n" +
3064 "%3 = OpFDiv %float %float_2 %2\n" +
3065 "%4 = OpFNegate %float %3\n" +
3069 // Test case 5: fold fnegate(fadd with const).
3070 // -(2.0 + x) = -2.0 - x
3071 InstructionFoldingCase<bool>(
3073 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3074 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
3075 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3076 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
3077 "%main = OpFunction %void None %void_func\n" +
3078 "%main_lab = OpLabel\n" +
3079 "%var = OpVariable %_ptr_float Function\n" +
3080 "%2 = OpLoad %float %var\n" +
3081 "%3 = OpFAdd %float %float_2 %2\n" +
3082 "%4 = OpFNegate %float %3\n" +
3086 // Test case 6: fold fnegate(fadd with const).
3087 // -(x + 2.0) = -2.0 - x
3088 InstructionFoldingCase<bool>(
3090 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3091 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
3092 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3093 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
3094 "%main = OpFunction %void None %void_func\n" +
3095 "%main_lab = OpLabel\n" +
3096 "%var = OpVariable %_ptr_float Function\n" +
3097 "%2 = OpLoad %float %var\n" +
3098 "%3 = OpFAdd %float %2 %float_2\n" +
3099 "%4 = OpFNegate %float %3\n" +
3103 // Test case 7: fold fnegate(fsub with const).
3104 // -(2.0 - x) = x - 2.0
3105 InstructionFoldingCase<bool>(
3107 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3108 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
3109 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3110 "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_2]]\n" +
3111 "%main = OpFunction %void None %void_func\n" +
3112 "%main_lab = OpLabel\n" +
3113 "%var = OpVariable %_ptr_float Function\n" +
3114 "%2 = OpLoad %float %var\n" +
3115 "%3 = OpFSub %float %float_2 %2\n" +
3116 "%4 = OpFNegate %float %3\n" +
3120 // Test case 8: fold fnegate(fsub with const).
3121 // -(x - 2.0) = 2.0 - x
3122 InstructionFoldingCase<bool>(
3124 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3125 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
3126 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3127 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
3128 "%main = OpFunction %void None %void_func\n" +
3129 "%main_lab = OpLabel\n" +
3130 "%var = OpVariable %_ptr_float Function\n" +
3131 "%2 = OpLoad %float %var\n" +
3132 "%3 = OpFSub %float %2 %float_2\n" +
3133 "%4 = OpFNegate %float %3\n" +
3137 // Test case 9: fold consecutive snegate
3139 InstructionFoldingCase<bool>(
3141 "; CHECK: [[ld:%\\w+]] = OpLoad [[int:%\\w+]]\n" +
3142 "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
3143 "%main = OpFunction %void None %void_func\n" +
3144 "%main_lab = OpLabel\n" +
3145 "%var = OpVariable %_ptr_int Function\n" +
3146 "%2 = OpLoad %int %var\n" +
3147 "%3 = OpSNegate %int %2\n" +
3148 "%4 = OpSNegate %int %3\n" +
3152 // Test case 10: fold consecutive vector negate
3154 InstructionFoldingCase<bool>(
3156 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float:%\\w+]]\n" +
3157 "; CHECK: %4 = OpCopyObject [[v2float]] [[ld]]\n" +
3158 "%main = OpFunction %void None %void_func\n" +
3159 "%main_lab = OpLabel\n" +
3160 "%var = OpVariable %_ptr_v2float Function\n" +
3161 "%2 = OpLoad %v2float %var\n" +
3162 "%3 = OpFNegate %v2float %2\n" +
3163 "%4 = OpFNegate %v2float %3\n" +
3167 // Test case 11: fold snegate(iadd with const).
3168 // -(2 + x) = -2 - x
3169 InstructionFoldingCase<bool>(
3171 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
3172 "; CHECK: OpConstant [[int]] -2147483648\n" +
3173 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
3174 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
3175 "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
3176 "%main = OpFunction %void None %void_func\n" +
3177 "%main_lab = OpLabel\n" +
3178 "%var = OpVariable %_ptr_int Function\n" +
3179 "%2 = OpLoad %int %var\n" +
3180 "%3 = OpIAdd %int %int_2 %2\n" +
3181 "%4 = OpSNegate %int %3\n" +
3185 // Test case 12: fold snegate(iadd with const).
3186 // -(x + 2) = -2 - x
3187 InstructionFoldingCase<bool>(
3189 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
3190 "; CHECK: OpConstant [[int]] -2147483648\n" +
3191 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
3192 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
3193 "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
3194 "%main = OpFunction %void None %void_func\n" +
3195 "%main_lab = OpLabel\n" +
3196 "%var = OpVariable %_ptr_int Function\n" +
3197 "%2 = OpLoad %int %var\n" +
3198 "%3 = OpIAdd %int %2 %int_2\n" +
3199 "%4 = OpSNegate %int %3\n" +
3203 // Test case 13: fold snegate(isub with const).
3205 InstructionFoldingCase<bool>(
3207 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
3208 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
3209 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
3210 "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_2]]\n" +
3211 "%main = OpFunction %void None %void_func\n" +
3212 "%main_lab = OpLabel\n" +
3213 "%var = OpVariable %_ptr_int Function\n" +
3214 "%2 = OpLoad %int %var\n" +
3215 "%3 = OpISub %int %int_2 %2\n" +
3216 "%4 = OpSNegate %int %3\n" +
3220 // Test case 14: fold snegate(isub with const).
3222 InstructionFoldingCase<bool>(
3224 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
3225 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
3226 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
3227 "; CHECK: %4 = OpISub [[int]] [[int_2]] [[ld]]\n" +
3228 "%main = OpFunction %void None %void_func\n" +
3229 "%main_lab = OpLabel\n" +
3230 "%var = OpVariable %_ptr_int Function\n" +
3231 "%2 = OpLoad %int %var\n" +
3232 "%3 = OpISub %int %2 %int_2\n" +
3233 "%4 = OpSNegate %int %3\n" +
3237 // Test case 15: fold snegate(iadd with const).
3238 // -(x + 2) = -2 - x
3239 InstructionFoldingCase<bool>(
3241 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
3242 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2\n" +
3243 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
3244 "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
3245 "%main = OpFunction %void None %void_func\n" +
3246 "%main_lab = OpLabel\n" +
3247 "%var = OpVariable %_ptr_long Function\n" +
3248 "%2 = OpLoad %long %var\n" +
3249 "%3 = OpIAdd %long %2 %long_2\n" +
3250 "%4 = OpSNegate %long %3\n" +
3254 // Test case 16: fold snegate(isub with const).
3256 InstructionFoldingCase<bool>(
3258 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
3259 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
3260 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
3261 "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_2]]\n" +
3262 "%main = OpFunction %void None %void_func\n" +
3263 "%main_lab = OpLabel\n" +
3264 "%var = OpVariable %_ptr_long Function\n" +
3265 "%2 = OpLoad %long %var\n" +
3266 "%3 = OpISub %long %long_2 %2\n" +
3267 "%4 = OpSNegate %long %3\n" +
3271 // Test case 17: fold snegate(isub with const).
3273 InstructionFoldingCase<bool>(
3275 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
3276 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
3277 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
3278 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
3279 "%main = OpFunction %void None %void_func\n" +
3280 "%main_lab = OpLabel\n" +
3281 "%var = OpVariable %_ptr_long Function\n" +
3282 "%2 = OpLoad %long %var\n" +
3283 "%3 = OpISub %long %2 %long_2\n" +
3284 "%4 = OpSNegate %long %3\n" +
3290 INSTANTIATE_TEST_CASE_P(ReciprocalFDivTest, MatchingInstructionFoldingTest,
3292 // Test case 0: scalar reicprocal
3293 // x / 0.5 = x * 2.0
3294 InstructionFoldingCase<bool>(
3296 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3297 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
3298 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3299 "; CHECK: %3 = OpFMul [[float]] [[ld]] [[float_2]]\n" +
3300 "%main = OpFunction %void None %void_func\n" +
3301 "%main_lab = OpLabel\n" +
3302 "%var = OpVariable %_ptr_float Function\n" +
3303 "%2 = OpLoad %float %var\n" +
3304 "%3 = OpFDiv %float %2 %float_0p5\n" +
3308 // Test case 1: Unfoldable
3309 InstructionFoldingCase<bool>(
3311 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3312 "; CHECK: [[float_0:%\\w+]] = OpConstant [[float]] 0\n" +
3313 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3314 "; CHECK: %3 = OpFDiv [[float]] [[ld]] [[float_0]]\n" +
3315 "%main = OpFunction %void None %void_func\n" +
3316 "%main_lab = OpLabel\n" +
3317 "%var = OpVariable %_ptr_float Function\n" +
3318 "%2 = OpLoad %float %var\n" +
3319 "%3 = OpFDiv %float %2 %104\n" +
3323 // Test case 2: Vector reciprocal
3324 // x / {2.0, 0.5} = x * {0.5, 2.0}
3325 InstructionFoldingCase<bool>(
3327 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3328 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
3329 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
3330 "; CHECK: [[float_0p5:%\\w+]] = OpConstant [[float]] 0.5\n" +
3331 "; CHECK: [[v2float_0p5_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_0p5]] [[float_2]]\n" +
3332 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
3333 "; CHECK: %3 = OpFMul [[v2float]] [[ld]] [[v2float_0p5_2]]\n" +
3334 "%main = OpFunction %void None %void_func\n" +
3335 "%main_lab = OpLabel\n" +
3336 "%var = OpVariable %_ptr_v2float Function\n" +
3337 "%2 = OpLoad %v2float %var\n" +
3338 "%3 = OpFDiv %v2float %2 %v2float_2_0p5\n" +
3342 // Test case 3: double reciprocal
3343 // x / 2.0 = x * 0.5
3344 InstructionFoldingCase<bool>(
3346 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
3347 "; CHECK: [[double_0p5:%\\w+]] = OpConstant [[double]] 0.5\n" +
3348 "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
3349 "; CHECK: %3 = OpFMul [[double]] [[ld]] [[double_0p5]]\n" +
3350 "%main = OpFunction %void None %void_func\n" +
3351 "%main_lab = OpLabel\n" +
3352 "%var = OpVariable %_ptr_double Function\n" +
3353 "%2 = OpLoad %double %var\n" +
3354 "%3 = OpFDiv %double %2 %double_2\n" +
3358 // Test case 4: don't fold x / 0.
3359 InstructionFoldingCase<bool>(
3361 "%main = OpFunction %void None %void_func\n" +
3362 "%main_lab = OpLabel\n" +
3363 "%var = OpVariable %_ptr_v2float Function\n" +
3364 "%2 = OpLoad %v2float %var\n" +
3365 "%3 = OpFDiv %v2float %2 %v2float_null\n" +
3371 INSTANTIATE_TEST_CASE_P(MergeMulTest, MatchingInstructionFoldingTest,
3373 // Test case 0: fold consecutive fmuls
3374 // (x * 3.0) * 2.0 = x * 6.0
3375 InstructionFoldingCase<bool>(
3377 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3378 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
3379 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3380 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
3381 "%main = OpFunction %void None %void_func\n" +
3382 "%main_lab = OpLabel\n" +
3383 "%var = OpVariable %_ptr_float Function\n" +
3384 "%2 = OpLoad %float %var\n" +
3385 "%3 = OpFMul %float %2 %float_3\n" +
3386 "%4 = OpFMul %float %3 %float_2\n" +
3390 // Test case 1: fold consecutive fmuls
3391 // 2.0 * (x * 3.0) = x * 6.0
3392 InstructionFoldingCase<bool>(
3394 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3395 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
3396 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3397 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
3398 "%main = OpFunction %void None %void_func\n" +
3399 "%main_lab = OpLabel\n" +
3400 "%var = OpVariable %_ptr_float Function\n" +
3401 "%2 = OpLoad %float %var\n" +
3402 "%3 = OpFMul %float %2 %float_3\n" +
3403 "%4 = OpFMul %float %float_2 %3\n" +
3407 // Test case 2: fold consecutive fmuls
3408 // (3.0 * x) * 2.0 = x * 6.0
3409 InstructionFoldingCase<bool>(
3411 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3412 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
3413 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3414 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
3415 "%main = OpFunction %void None %void_func\n" +
3416 "%main_lab = OpLabel\n" +
3417 "%var = OpVariable %_ptr_float Function\n" +
3418 "%2 = OpLoad %float %var\n" +
3419 "%3 = OpFMul %float %float_3 %2\n" +
3420 "%4 = OpFMul %float %float_2 %3\n" +
3424 // Test case 3: fold vector fmul
3425 InstructionFoldingCase<bool>(
3427 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3428 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
3429 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
3430 "; CHECK: [[v2float_6_6:%\\w+]] = OpConstantComposite [[v2float]] [[float_6]] [[float_6]]\n" +
3431 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
3432 "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_6_6]]\n" +
3433 "%main = OpFunction %void None %void_func\n" +
3434 "%main_lab = OpLabel\n" +
3435 "%var = OpVariable %_ptr_v2float Function\n" +
3436 "%2 = OpLoad %v2float %var\n" +
3437 "%3 = OpFMul %v2float %2 %v2float_2_3\n" +
3438 "%4 = OpFMul %v2float %3 %v2float_3_2\n" +
3442 // Test case 4: fold double fmuls
3443 // (x * 3.0) * 2.0 = x * 6.0
3444 InstructionFoldingCase<bool>(
3446 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
3447 "; CHECK: [[double_6:%\\w+]] = OpConstant [[double]] 6\n" +
3448 "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
3449 "; CHECK: %4 = OpFMul [[double]] [[ld]] [[double_6]]\n" +
3450 "%main = OpFunction %void None %void_func\n" +
3451 "%main_lab = OpLabel\n" +
3452 "%var = OpVariable %_ptr_double Function\n" +
3453 "%2 = OpLoad %double %var\n" +
3454 "%3 = OpFMul %double %2 %double_3\n" +
3455 "%4 = OpFMul %double %3 %double_2\n" +
3459 // Test case 5: fold 32 bit imuls
3460 // (x * 3) * 2 = x * 6
3461 InstructionFoldingCase<bool>(
3463 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
3464 "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
3465 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
3466 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_6]]\n" +
3467 "%main = OpFunction %void None %void_func\n" +
3468 "%main_lab = OpLabel\n" +
3469 "%var = OpVariable %_ptr_int Function\n" +
3470 "%2 = OpLoad %int %var\n" +
3471 "%3 = OpIMul %int %2 %int_3\n" +
3472 "%4 = OpIMul %int %3 %int_2\n" +
3476 // Test case 6: fold 64 bit imuls
3477 // (x * 3) * 2 = x * 6
3478 InstructionFoldingCase<bool>(
3480 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
3481 "; CHECK: [[long_6:%\\w+]] = OpConstant [[long]] 6\n" +
3482 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
3483 "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_6]]\n" +
3484 "%main = OpFunction %void None %void_func\n" +
3485 "%main_lab = OpLabel\n" +
3486 "%var = OpVariable %_ptr_long Function\n" +
3487 "%2 = OpLoad %long %var\n" +
3488 "%3 = OpIMul %long %2 %long_3\n" +
3489 "%4 = OpIMul %long %3 %long_2\n" +
3493 // Test case 7: merge vector integer mults
3494 InstructionFoldingCase<bool>(
3496 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
3497 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
3498 "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
3499 "; CHECK: [[v2int_6_6:%\\w+]] = OpConstantComposite [[v2int]] [[int_6]] [[int_6]]\n" +
3500 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
3501 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_6_6]]\n" +
3502 "%main = OpFunction %void None %void_func\n" +
3503 "%main_lab = OpLabel\n" +
3504 "%var = OpVariable %_ptr_v2int Function\n" +
3505 "%2 = OpLoad %v2int %var\n" +
3506 "%3 = OpIMul %v2int %2 %v2int_2_3\n" +
3507 "%4 = OpIMul %v2int %3 %v2int_3_2\n" +
3511 // Test case 8: merge fmul of fdiv
3512 // 2.0 * (2.0 / x) = 4.0 / x
3513 InstructionFoldingCase<bool>(
3515 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3516 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
3517 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3518 "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
3519 "%main = OpFunction %void None %void_func\n" +
3520 "%main_lab = OpLabel\n" +
3521 "%var = OpVariable %_ptr_float Function\n" +
3522 "%2 = OpLoad %float %var\n" +
3523 "%3 = OpFDiv %float %float_2 %2\n" +
3524 "%4 = OpFMul %float %float_2 %3\n" +
3528 // Test case 9: merge fmul of fdiv
3529 // (2.0 / x) * 2.0 = 4.0 / x
3530 InstructionFoldingCase<bool>(
3532 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3533 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
3534 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3535 "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
3536 "%main = OpFunction %void None %void_func\n" +
3537 "%main_lab = OpLabel\n" +
3538 "%var = OpVariable %_ptr_float Function\n" +
3539 "%2 = OpLoad %float %var\n" +
3540 "%3 = OpFDiv %float %float_2 %2\n" +
3541 "%4 = OpFMul %float %3 %float_2\n" +
3545 // Test case 10: Do not merge imul of sdiv
3547 InstructionFoldingCase<bool>(
3549 "%main = OpFunction %void None %void_func\n" +
3550 "%main_lab = OpLabel\n" +
3551 "%var = OpVariable %_ptr_int Function\n" +
3552 "%2 = OpLoad %int %var\n" +
3553 "%3 = OpSDiv %int %2 %int_2\n" +
3554 "%4 = OpIMul %int %int_4 %3\n" +
3558 // Test case 11: Do not merge imul of sdiv
3560 InstructionFoldingCase<bool>(
3562 "%main = OpFunction %void None %void_func\n" +
3563 "%main_lab = OpLabel\n" +
3564 "%var = OpVariable %_ptr_int Function\n" +
3565 "%2 = OpLoad %int %var\n" +
3566 "%3 = OpSDiv %int %2 %int_2\n" +
3567 "%4 = OpIMul %int %3 %int_4\n" +
3571 // Test case 12: Do not merge imul of udiv
3573 InstructionFoldingCase<bool>(
3575 "%main = OpFunction %void None %void_func\n" +
3576 "%main_lab = OpLabel\n" +
3577 "%var = OpVariable %_ptr_uint Function\n" +
3578 "%2 = OpLoad %uint %var\n" +
3579 "%3 = OpUDiv %uint %2 %uint_2\n" +
3580 "%4 = OpIMul %uint %uint_4 %3\n" +
3584 // Test case 13: Do not merge imul of udiv
3586 InstructionFoldingCase<bool>(
3588 "%main = OpFunction %void None %void_func\n" +
3589 "%main_lab = OpLabel\n" +
3590 "%var = OpVariable %_ptr_uint Function\n" +
3591 "%2 = OpLoad %uint %var\n" +
3592 "%3 = OpUDiv %uint %2 %uint_2\n" +
3593 "%4 = OpIMul %uint %3 %uint_4\n" +
3597 // Test case 14: Don't fold
3599 InstructionFoldingCase<bool>(
3601 "%main = OpFunction %void None %void_func\n" +
3602 "%main_lab = OpLabel\n" +
3603 "%var = OpVariable %_ptr_uint Function\n" +
3604 "%2 = OpLoad %uint %var\n" +
3605 "%3 = OpUDiv %uint %2 %uint_3\n" +
3606 "%4 = OpIMul %uint %3 %uint_4\n" +
3610 // Test case 15: merge vector fmul of fdiv
3611 // (x / {2,2}) * {4,4} = x * {2,2}
3612 InstructionFoldingCase<bool>(
3614 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3615 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
3616 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
3617 "; CHECK: [[v2float_2_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_2]] [[float_2]]\n" +
3618 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
3619 "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_2_2]]\n" +
3620 "%main = OpFunction %void None %void_func\n" +
3621 "%main_lab = OpLabel\n" +
3622 "%var = OpVariable %_ptr_v2float Function\n" +
3623 "%2 = OpLoad %v2float %var\n" +
3624 "%3 = OpFDiv %v2float %2 %v2float_2_2\n" +
3625 "%4 = OpFMul %v2float %3 %v2float_4_4\n" +
3629 // Test case 16: merge vector imul of snegate
3630 // (-x) * {2,2} = x * {-2,-2}
3631 InstructionFoldingCase<bool>(
3633 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
3634 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
3635 "; CHECK: OpConstant [[int]] -2147483648\n" +
3636 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
3637 "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
3638 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
3639 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
3640 "%main = OpFunction %void None %void_func\n" +
3641 "%main_lab = OpLabel\n" +
3642 "%var = OpVariable %_ptr_v2int Function\n" +
3643 "%2 = OpLoad %v2int %var\n" +
3644 "%3 = OpSNegate %v2int %2\n" +
3645 "%4 = OpIMul %v2int %3 %v2int_2_2\n" +
3649 // Test case 17: merge vector imul of snegate
3650 // {2,2} * (-x) = x * {-2,-2}
3651 InstructionFoldingCase<bool>(
3653 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
3654 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
3655 "; CHECK: OpConstant [[int]] -2147483648\n" +
3656 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
3657 "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
3658 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
3659 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
3660 "%main = OpFunction %void None %void_func\n" +
3661 "%main_lab = OpLabel\n" +
3662 "%var = OpVariable %_ptr_v2int Function\n" +
3663 "%2 = OpLoad %v2int %var\n" +
3664 "%3 = OpSNegate %v2int %2\n" +
3665 "%4 = OpIMul %v2int %v2int_2_2 %3\n" +
3671 INSTANTIATE_TEST_CASE_P(MergeDivTest, MatchingInstructionFoldingTest,
3673 // Test case 0: merge consecutive fdiv
3674 // 4.0 / (2.0 / x) = 2.0 * x
3675 InstructionFoldingCase<bool>(
3677 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3678 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
3679 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3680 "; CHECK: %4 = OpFMul [[float]] [[float_2]] [[ld]]\n" +
3681 "%main = OpFunction %void None %void_func\n" +
3682 "%main_lab = OpLabel\n" +
3683 "%var = OpVariable %_ptr_float Function\n" +
3684 "%2 = OpLoad %float %var\n" +
3685 "%3 = OpFDiv %float %float_2 %2\n" +
3686 "%4 = OpFDiv %float %float_4 %3\n" +
3690 // Test case 1: merge consecutive fdiv
3691 // 4.0 / (x / 2.0) = 8.0 / x
3692 InstructionFoldingCase<bool>(
3694 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3695 "; CHECK: [[float_8:%\\w+]] = OpConstant [[float]] 8\n" +
3696 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3697 "; CHECK: %4 = OpFDiv [[float]] [[float_8]] [[ld]]\n" +
3698 "%main = OpFunction %void None %void_func\n" +
3699 "%main_lab = OpLabel\n" +
3700 "%var = OpVariable %_ptr_float Function\n" +
3701 "%2 = OpLoad %float %var\n" +
3702 "%3 = OpFDiv %float %2 %float_2\n" +
3703 "%4 = OpFDiv %float %float_4 %3\n" +
3707 // Test case 2: merge consecutive fdiv
3708 // (4.0 / x) / 2.0 = 2.0 / x
3709 InstructionFoldingCase<bool>(
3711 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3712 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
3713 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3714 "; CHECK: %4 = OpFDiv [[float]] [[float_2]] [[ld]]\n" +
3715 "%main = OpFunction %void None %void_func\n" +
3716 "%main_lab = OpLabel\n" +
3717 "%var = OpVariable %_ptr_float Function\n" +
3718 "%2 = OpLoad %float %var\n" +
3719 "%3 = OpFDiv %float %float_4 %2\n" +
3720 "%4 = OpFDiv %float %3 %float_2\n" +
3724 // Test case 3: Do not merge consecutive sdiv
3726 InstructionFoldingCase<bool>(
3728 "%main = OpFunction %void None %void_func\n" +
3729 "%main_lab = OpLabel\n" +
3730 "%var = OpVariable %_ptr_int Function\n" +
3731 "%2 = OpLoad %int %var\n" +
3732 "%3 = OpSDiv %int %int_2 %2\n" +
3733 "%4 = OpSDiv %int %int_4 %3\n" +
3737 // Test case 4: Do not merge consecutive sdiv
3739 InstructionFoldingCase<bool>(
3741 "%main = OpFunction %void None %void_func\n" +
3742 "%main_lab = OpLabel\n" +
3743 "%var = OpVariable %_ptr_int Function\n" +
3744 "%2 = OpLoad %int %var\n" +
3745 "%3 = OpSDiv %int %2 %int_2\n" +
3746 "%4 = OpSDiv %int %int_4 %3\n" +
3750 // Test case 5: Do not merge consecutive sdiv
3752 InstructionFoldingCase<bool>(
3754 "%main = OpFunction %void None %void_func\n" +
3755 "%main_lab = OpLabel\n" +
3756 "%var = OpVariable %_ptr_int Function\n" +
3757 "%2 = OpLoad %int %var\n" +
3758 "%3 = OpSDiv %int %int_4 %2\n" +
3759 "%4 = OpSDiv %int %3 %int_2\n" +
3763 // Test case 6: Do not merge consecutive sdiv
3765 InstructionFoldingCase<bool>(
3767 "%main = OpFunction %void None %void_func\n" +
3768 "%main_lab = OpLabel\n" +
3769 "%var = OpVariable %_ptr_int Function\n" +
3770 "%2 = OpLoad %int %var\n" +
3771 "%3 = OpSDiv %int %2 %int_4\n" +
3772 "%4 = OpSDiv %int %3 %int_2\n" +
3776 // Test case 7: Do not merge sdiv of imul
3778 InstructionFoldingCase<bool>(
3780 "%main = OpFunction %void None %void_func\n" +
3781 "%main_lab = OpLabel\n" +
3782 "%var = OpVariable %_ptr_int Function\n" +
3783 "%2 = OpLoad %int %var\n" +
3784 "%3 = OpIMul %int %int_2 %2\n" +
3785 "%4 = OpSDiv %int %int_4 %3\n" +
3789 // Test case 8: Do not merge sdiv of imul
3791 InstructionFoldingCase<bool>(
3793 "%main = OpFunction %void None %void_func\n" +
3794 "%main_lab = OpLabel\n" +
3795 "%var = OpVariable %_ptr_int Function\n" +
3796 "%2 = OpLoad %int %var\n" +
3797 "%3 = OpIMul %int %2 %int_2\n" +
3798 "%4 = OpSDiv %int %int_4 %3\n" +
3802 // Test case 9: Do not merge sdiv of imul
3804 InstructionFoldingCase<bool>(
3806 "%main = OpFunction %void None %void_func\n" +
3807 "%main_lab = OpLabel\n" +
3808 "%var = OpVariable %_ptr_int Function\n" +
3809 "%2 = OpLoad %int %var\n" +
3810 "%3 = OpIMul %int %int_4 %2\n" +
3811 "%4 = OpSDiv %int %3 %int_2\n" +
3815 // Test case 10: Do not merge sdiv of imul
3817 InstructionFoldingCase<bool>(
3819 "%main = OpFunction %void None %void_func\n" +
3820 "%main_lab = OpLabel\n" +
3821 "%var = OpVariable %_ptr_int Function\n" +
3822 "%2 = OpLoad %int %var\n" +
3823 "%3 = OpIMul %int %2 %int_4\n" +
3824 "%4 = OpSDiv %int %3 %int_2\n" +
3828 // Test case 11: merge sdiv of snegate
3829 // (-x) / 2 = x / -2
3830 InstructionFoldingCase<bool>(
3832 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
3833 "; CHECK: OpConstant [[int]] -2147483648\n" +
3834 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
3835 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
3836 "; CHECK: %4 = OpSDiv [[int]] [[ld]] [[int_n2]]\n" +
3837 "%main = OpFunction %void None %void_func\n" +
3838 "%main_lab = OpLabel\n" +
3839 "%var = OpVariable %_ptr_int Function\n" +
3840 "%2 = OpLoad %int %var\n" +
3841 "%3 = OpSNegate %int %2\n" +
3842 "%4 = OpSDiv %int %3 %int_2\n" +
3846 // Test case 12: merge sdiv of snegate
3847 // 2 / (-x) = -2 / x
3848 InstructionFoldingCase<bool>(
3850 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
3851 "; CHECK: OpConstant [[int]] -2147483648\n" +
3852 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2\n" +
3853 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
3854 "; CHECK: %4 = OpSDiv [[int]] [[int_n2]] [[ld]]\n" +
3855 "%main = OpFunction %void None %void_func\n" +
3856 "%main_lab = OpLabel\n" +
3857 "%var = OpVariable %_ptr_int Function\n" +
3858 "%2 = OpLoad %int %var\n" +
3859 "%3 = OpSNegate %int %2\n" +
3860 "%4 = OpSDiv %int %int_2 %3\n" +
3864 // Test case 13: Don't merge
3865 // (x / {null}) / {null}
3866 InstructionFoldingCase<bool>(
3868 "%main = OpFunction %void None %void_func\n" +
3869 "%main_lab = OpLabel\n" +
3870 "%var = OpVariable %_ptr_v2float Function\n" +
3871 "%2 = OpLoad %float %var\n" +
3872 "%3 = OpFDiv %float %2 %v2float_null\n" +
3873 "%4 = OpFDiv %float %3 %v2float_null\n" +
3879 INSTANTIATE_TEST_CASE_P(MergeAddTest, MatchingInstructionFoldingTest,
3881 // Test case 0: merge add of negate
3883 InstructionFoldingCase<bool>(
3885 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3886 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
3887 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3888 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
3889 "%main = OpFunction %void None %void_func\n" +
3890 "%main_lab = OpLabel\n" +
3891 "%var = OpVariable %_ptr_float Function\n" +
3892 "%2 = OpLoad %float %var\n" +
3893 "%3 = OpFNegate %float %2\n" +
3894 "%4 = OpFAdd %float %3 %float_2\n" +
3898 // Test case 1: merge add of negate
3900 InstructionFoldingCase<bool>(
3902 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3903 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
3904 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3905 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
3906 "%main = OpFunction %void None %void_func\n" +
3907 "%main_lab = OpLabel\n" +
3908 "%var = OpVariable %_ptr_float Function\n" +
3909 "%2 = OpLoad %float %var\n" +
3910 "%3 = OpSNegate %float %2\n" +
3911 "%4 = OpIAdd %float %float_2 %3\n" +
3915 // Test case 2: merge add of negate
3917 InstructionFoldingCase<bool>(
3919 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
3920 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
3921 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
3922 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
3923 "%main = OpFunction %void None %void_func\n" +
3924 "%main_lab = OpLabel\n" +
3925 "%var = OpVariable %_ptr_long Function\n" +
3926 "%2 = OpLoad %long %var\n" +
3927 "%3 = OpSNegate %long %2\n" +
3928 "%4 = OpIAdd %long %3 %long_2\n" +
3932 // Test case 3: merge add of negate
3934 InstructionFoldingCase<bool>(
3936 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
3937 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
3938 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
3939 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
3940 "%main = OpFunction %void None %void_func\n" +
3941 "%main_lab = OpLabel\n" +
3942 "%var = OpVariable %_ptr_long Function\n" +
3943 "%2 = OpLoad %long %var\n" +
3944 "%3 = OpSNegate %long %2\n" +
3945 "%4 = OpIAdd %long %long_2 %3\n" +
3949 // Test case 4: merge add of subtract
3950 // (x - 1) + 2 = x + 1
3951 InstructionFoldingCase<bool>(
3953 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3954 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
3955 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3956 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
3957 "%main = OpFunction %void None %void_func\n" +
3958 "%main_lab = OpLabel\n" +
3959 "%var = OpVariable %_ptr_float Function\n" +
3960 "%2 = OpLoad %float %var\n" +
3961 "%3 = OpFSub %float %2 %float_1\n" +
3962 "%4 = OpFAdd %float %3 %float_2\n" +
3966 // Test case 5: merge add of subtract
3967 // (1 - x) + 2 = 3 - x
3968 InstructionFoldingCase<bool>(
3970 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3971 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
3972 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3973 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
3974 "%main = OpFunction %void None %void_func\n" +
3975 "%main_lab = OpLabel\n" +
3976 "%var = OpVariable %_ptr_float Function\n" +
3977 "%2 = OpLoad %float %var\n" +
3978 "%3 = OpFSub %float %float_1 %2\n" +
3979 "%4 = OpFAdd %float %3 %float_2\n" +
3983 // Test case 6: merge add of subtract
3984 // 2 + (x - 1) = x + 1
3985 InstructionFoldingCase<bool>(
3987 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
3988 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
3989 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
3990 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
3991 "%main = OpFunction %void None %void_func\n" +
3992 "%main_lab = OpLabel\n" +
3993 "%var = OpVariable %_ptr_float Function\n" +
3994 "%2 = OpLoad %float %var\n" +
3995 "%3 = OpFSub %float %2 %float_1\n" +
3996 "%4 = OpFAdd %float %float_2 %3\n" +
4000 // Test case 7: merge add of subtract
4001 // 2 + (1 - x) = 3 - x
4002 InstructionFoldingCase<bool>(
4004 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4005 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
4006 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4007 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
4008 "%main = OpFunction %void None %void_func\n" +
4009 "%main_lab = OpLabel\n" +
4010 "%var = OpVariable %_ptr_float Function\n" +
4011 "%2 = OpLoad %float %var\n" +
4012 "%3 = OpFSub %float %float_1 %2\n" +
4013 "%4 = OpFAdd %float %float_2 %3\n" +
4017 // Test case 8: merge add of add
4018 // (x + 1) + 2 = x + 3
4019 InstructionFoldingCase<bool>(
4021 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4022 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
4023 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4024 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
4025 "%main = OpFunction %void None %void_func\n" +
4026 "%main_lab = OpLabel\n" +
4027 "%var = OpVariable %_ptr_float Function\n" +
4028 "%2 = OpLoad %float %var\n" +
4029 "%3 = OpFAdd %float %2 %float_1\n" +
4030 "%4 = OpFAdd %float %3 %float_2\n" +
4034 // Test case 9: merge add of add
4035 // (1 + x) + 2 = 3 + x
4036 InstructionFoldingCase<bool>(
4038 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4039 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
4040 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4041 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
4042 "%main = OpFunction %void None %void_func\n" +
4043 "%main_lab = OpLabel\n" +
4044 "%var = OpVariable %_ptr_float Function\n" +
4045 "%2 = OpLoad %float %var\n" +
4046 "%3 = OpFAdd %float %float_1 %2\n" +
4047 "%4 = OpFAdd %float %3 %float_2\n" +
4051 // Test case 10: merge add of add
4052 // 2 + (x + 1) = x + 1
4053 InstructionFoldingCase<bool>(
4055 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4056 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
4057 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4058 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
4059 "%main = OpFunction %void None %void_func\n" +
4060 "%main_lab = OpLabel\n" +
4061 "%var = OpVariable %_ptr_float Function\n" +
4062 "%2 = OpLoad %float %var\n" +
4063 "%3 = OpFAdd %float %2 %float_1\n" +
4064 "%4 = OpFAdd %float %float_2 %3\n" +
4068 // Test case 11: merge add of add
4069 // 2 + (1 + x) = 3 - x
4070 InstructionFoldingCase<bool>(
4072 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4073 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
4074 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4075 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
4076 "%main = OpFunction %void None %void_func\n" +
4077 "%main_lab = OpLabel\n" +
4078 "%var = OpVariable %_ptr_float Function\n" +
4079 "%2 = OpLoad %float %var\n" +
4080 "%3 = OpFAdd %float %float_1 %2\n" +
4081 "%4 = OpFAdd %float %float_2 %3\n" +
4087 INSTANTIATE_TEST_CASE_P(MergeSubTest, MatchingInstructionFoldingTest,
4089 // Test case 0: merge sub of negate
4090 // (-x) - 2 = -2 - x
4091 InstructionFoldingCase<bool>(
4093 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4094 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2\n" +
4095 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4096 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
4097 "%main = OpFunction %void None %void_func\n" +
4098 "%main_lab = OpLabel\n" +
4099 "%var = OpVariable %_ptr_float Function\n" +
4100 "%2 = OpLoad %float %var\n" +
4101 "%3 = OpFNegate %float %2\n" +
4102 "%4 = OpFSub %float %3 %float_2\n" +
4106 // Test case 1: merge sub of negate
4108 InstructionFoldingCase<bool>(
4110 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4111 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
4112 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4113 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_2]]\n" +
4114 "%main = OpFunction %void None %void_func\n" +
4115 "%main_lab = OpLabel\n" +
4116 "%var = OpVariable %_ptr_float Function\n" +
4117 "%2 = OpLoad %float %var\n" +
4118 "%3 = OpFNegate %float %2\n" +
4119 "%4 = OpFSub %float %float_2 %3\n" +
4123 // Test case 2: merge sub of negate
4124 // (-x) - 2 = -2 - x
4125 InstructionFoldingCase<bool>(
4127 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
4128 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2\n" +
4129 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
4130 "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
4131 "%main = OpFunction %void None %void_func\n" +
4132 "%main_lab = OpLabel\n" +
4133 "%var = OpVariable %_ptr_long Function\n" +
4134 "%2 = OpLoad %long %var\n" +
4135 "%3 = OpSNegate %long %2\n" +
4136 "%4 = OpISub %long %3 %long_2\n" +
4140 // Test case 3: merge sub of negate
4142 InstructionFoldingCase<bool>(
4144 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
4145 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
4146 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
4147 "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_2]]\n" +
4148 "%main = OpFunction %void None %void_func\n" +
4149 "%main_lab = OpLabel\n" +
4150 "%var = OpVariable %_ptr_long Function\n" +
4151 "%2 = OpLoad %long %var\n" +
4152 "%3 = OpSNegate %long %2\n" +
4153 "%4 = OpISub %long %long_2 %3\n" +
4157 // Test case 4: merge add of subtract
4158 // (x + 2) - 1 = x + 1
4159 InstructionFoldingCase<bool>(
4161 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4162 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
4163 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4164 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
4165 "%main = OpFunction %void None %void_func\n" +
4166 "%main_lab = OpLabel\n" +
4167 "%var = OpVariable %_ptr_float Function\n" +
4168 "%2 = OpLoad %float %var\n" +
4169 "%3 = OpFAdd %float %2 %float_2\n" +
4170 "%4 = OpFSub %float %3 %float_1\n" +
4174 // Test case 5: merge add of subtract
4175 // (2 + x) - 1 = x + 1
4176 InstructionFoldingCase<bool>(
4178 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4179 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
4180 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4181 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
4182 "%main = OpFunction %void None %void_func\n" +
4183 "%main_lab = OpLabel\n" +
4184 "%var = OpVariable %_ptr_float Function\n" +
4185 "%2 = OpLoad %float %var\n" +
4186 "%3 = OpFAdd %float %float_2 %2\n" +
4187 "%4 = OpFSub %float %3 %float_1\n" +
4191 // Test case 6: merge add of subtract
4192 // 2 - (x + 1) = 1 - x
4193 InstructionFoldingCase<bool>(
4195 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4196 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
4197 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4198 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
4199 "%main = OpFunction %void None %void_func\n" +
4200 "%main_lab = OpLabel\n" +
4201 "%var = OpVariable %_ptr_float Function\n" +
4202 "%2 = OpLoad %float %var\n" +
4203 "%3 = OpFAdd %float %2 %float_1\n" +
4204 "%4 = OpFSub %float %float_2 %3\n" +
4208 // Test case 7: merge add of subtract
4209 // 2 - (1 + x) = 1 - x
4210 InstructionFoldingCase<bool>(
4212 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4213 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
4214 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4215 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
4216 "%main = OpFunction %void None %void_func\n" +
4217 "%main_lab = OpLabel\n" +
4218 "%var = OpVariable %_ptr_float Function\n" +
4219 "%2 = OpLoad %float %var\n" +
4220 "%3 = OpFAdd %float %float_1 %2\n" +
4221 "%4 = OpFSub %float %float_2 %3\n" +
4225 // Test case 8: merge subtract of subtract
4226 // (x - 2) - 1 = x - 3
4227 InstructionFoldingCase<bool>(
4229 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4230 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
4231 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4232 "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_3]]\n" +
4233 "%main = OpFunction %void None %void_func\n" +
4234 "%main_lab = OpLabel\n" +
4235 "%var = OpVariable %_ptr_float Function\n" +
4236 "%2 = OpLoad %float %var\n" +
4237 "%3 = OpFSub %float %2 %float_2\n" +
4238 "%4 = OpFSub %float %3 %float_1\n" +
4242 // Test case 9: merge subtract of subtract
4243 // (2 - x) - 1 = 1 - x
4244 InstructionFoldingCase<bool>(
4246 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4247 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
4248 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4249 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
4250 "%main = OpFunction %void None %void_func\n" +
4251 "%main_lab = OpLabel\n" +
4252 "%var = OpVariable %_ptr_float Function\n" +
4253 "%2 = OpLoad %float %var\n" +
4254 "%3 = OpFSub %float %float_2 %2\n" +
4255 "%4 = OpFSub %float %3 %float_1\n" +
4259 // Test case 10: merge subtract of subtract
4260 // 2 - (x - 1) = 3 - x
4261 InstructionFoldingCase<bool>(
4263 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4264 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
4265 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4266 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
4267 "%main = OpFunction %void None %void_func\n" +
4268 "%main_lab = OpLabel\n" +
4269 "%var = OpVariable %_ptr_float Function\n" +
4270 "%2 = OpLoad %float %var\n" +
4271 "%3 = OpFSub %float %2 %float_1\n" +
4272 "%4 = OpFSub %float %float_2 %3\n" +
4276 // Test case 11: merge subtract of subtract
4277 // 1 - (2 - x) = x + (-1)
4278 InstructionFoldingCase<bool>(
4280 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4281 "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
4282 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4283 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_n1]]\n" +
4284 "%main = OpFunction %void None %void_func\n" +
4285 "%main_lab = OpLabel\n" +
4286 "%var = OpVariable %_ptr_float Function\n" +
4287 "%2 = OpLoad %float %var\n" +
4288 "%3 = OpFSub %float %float_2 %2\n" +
4289 "%4 = OpFSub %float %float_1 %3\n" +
4293 // Test case 12: merge subtract of subtract
4294 // 2 - (1 - x) = x + 1
4295 InstructionFoldingCase<bool>(
4297 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
4298 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
4299 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
4300 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
4301 "%main = OpFunction %void None %void_func\n" +
4302 "%main_lab = OpLabel\n" +
4303 "%var = OpVariable %_ptr_float Function\n" +
4304 "%2 = OpLoad %float %var\n" +
4305 "%3 = OpFSub %float %float_1 %2\n" +
4306 "%4 = OpFSub %float %float_2 %3\n" +
4312 INSTANTIATE_TEST_CASE_P(SelectFoldingTest, MatchingInstructionFoldingTest,
4314 // Test case 0: Fold select with the same values for both sides
4315 InstructionFoldingCase<bool>(
4317 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4318 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
4319 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
4320 "%main = OpFunction %void None %void_func\n" +
4321 "%main_lab = OpLabel\n" +
4322 "%n = OpVariable %_ptr_bool Function\n" +
4323 "%load = OpLoad %bool %n\n" +
4324 "%2 = OpSelect %int %load %100 %100\n" +
4328 // Test case 1: Fold select true to left side
4329 InstructionFoldingCase<bool>(
4331 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4332 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
4333 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
4334 "%main = OpFunction %void None %void_func\n" +
4335 "%main_lab = OpLabel\n" +
4336 "%n = OpVariable %_ptr_int Function\n" +
4337 "%load = OpLoad %bool %n\n" +
4338 "%2 = OpSelect %int %true %100 %n\n" +
4342 // Test case 2: Fold select false to right side
4343 InstructionFoldingCase<bool>(
4345 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4346 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
4347 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
4348 "%main = OpFunction %void None %void_func\n" +
4349 "%main_lab = OpLabel\n" +
4350 "%n = OpVariable %_ptr_int Function\n" +
4351 "%load = OpLoad %bool %n\n" +
4352 "%2 = OpSelect %int %false %n %100\n" +
4356 // Test case 3: Fold select null to right side
4357 InstructionFoldingCase<bool>(
4359 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4360 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
4361 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
4362 "%main = OpFunction %void None %void_func\n" +
4363 "%main_lab = OpLabel\n" +
4364 "%n = OpVariable %_ptr_int Function\n" +
4365 "%load = OpLoad %int %n\n" +
4366 "%2 = OpSelect %int %bool_null %load %100\n" +
4370 // Test case 4: vector null
4371 InstructionFoldingCase<bool>(
4373 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4374 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
4375 "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
4376 "; CHECK: [[v2int2_2:%\\w+]] = OpConstantComposite [[v2int]] [[int2]] [[int2]]\n" +
4377 "; CHECK: %2 = OpCopyObject [[v2int]] [[v2int2_2]]\n" +
4378 "%main = OpFunction %void None %void_func\n" +
4379 "%main_lab = OpLabel\n" +
4380 "%n = OpVariable %_ptr_v2int Function\n" +
4381 "%load = OpLoad %v2int %n\n" +
4382 "%2 = OpSelect %v2int %v2bool_null %load %v2int_2_2\n" +
4386 // Test case 5: vector select
4387 InstructionFoldingCase<bool>(
4389 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4390 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
4391 "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 0 3\n" +
4392 "%main = OpFunction %void None %void_func\n" +
4393 "%main_lab = OpLabel\n" +
4394 "%m = OpVariable %_ptr_v2int Function\n" +
4395 "%n = OpVariable %_ptr_v2int Function\n" +
4396 "%2 = OpLoad %v2int %n\n" +
4397 "%3 = OpLoad %v2int %n\n" +
4398 "%4 = OpSelect %v2int %v2bool_true_false %2 %3\n" +
4402 // Test case 6: vector select
4403 InstructionFoldingCase<bool>(
4405 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4406 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
4407 "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 2 1\n" +
4408 "%main = OpFunction %void None %void_func\n" +
4409 "%main_lab = OpLabel\n" +
4410 "%m = OpVariable %_ptr_v2int Function\n" +
4411 "%n = OpVariable %_ptr_v2int Function\n" +
4412 "%2 = OpLoad %v2int %n\n" +
4413 "%3 = OpLoad %v2int %n\n" +
4414 "%4 = OpSelect %v2int %v2bool_false_true %2 %3\n" +
4420 INSTANTIATE_TEST_CASE_P(CompositeExtractMatchingTest, MatchingInstructionFoldingTest,
4422 // Test case 0: Extracting from result of consecutive shuffles of differing
4424 InstructionFoldingCase<bool>(
4426 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4427 "; CHECK: %5 = OpCompositeExtract [[int]] %2 2\n" +
4428 "%main = OpFunction %void None %void_func\n" +
4429 "%main_lab = OpLabel\n" +
4430 "%n = OpVariable %_ptr_v4int Function\n" +
4431 "%2 = OpLoad %v4int %n\n" +
4432 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
4433 "%4 = OpVectorShuffle %v4int %2 %3 0 4 2 5\n" +
4434 "%5 = OpCompositeExtract %int %4 1\n" +
4438 // Test case 1: Extracting from result of vector shuffle of differing
4439 // input and result sizes.
4440 InstructionFoldingCase<bool>(
4442 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4443 "; CHECK: %4 = OpCompositeExtract [[int]] %2 2\n" +
4444 "%main = OpFunction %void None %void_func\n" +
4445 "%main_lab = OpLabel\n" +
4446 "%n = OpVariable %_ptr_v4int Function\n" +
4447 "%2 = OpLoad %v4int %n\n" +
4448 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
4449 "%4 = OpCompositeExtract %int %3 0\n" +
4453 // Test case 2: Extracting from result of vector shuffle of differing
4454 // input and result sizes.
4455 InstructionFoldingCase<bool>(
4457 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
4458 "; CHECK: %4 = OpCompositeExtract [[int]] %2 3\n" +
4459 "%main = OpFunction %void None %void_func\n" +
4460 "%main_lab = OpLabel\n" +
4461 "%n = OpVariable %_ptr_v4int Function\n" +
4462 "%2 = OpLoad %v4int %n\n" +
4463 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
4464 "%4 = OpCompositeExtract %int %3 1\n" +
4470 } // anonymous namespace