1 // Copyright (c) 2016 Google Inc.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13
14 #include "source/opt/fold.h"
15
16 #include <limits>
17 #include <memory>
18 #include <string>
19 #include <vector>
20
21 #include "effcee/effcee.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "source/opt/build_module.h"
25 #include "source/opt/def_use_manager.h"
26 #include "source/opt/ir_context.h"
27 #include "source/opt/module.h"
28 #include "spirv-tools/libspirv.hpp"
29
30 namespace spvtools {
31 namespace opt {
32 namespace {
33
34 using ::testing::Contains;
35
Disassemble(const std::string & original,IRContext * context,uint32_t disassemble_options=0)36 std::string Disassemble(const std::string& original, IRContext* context,
37 uint32_t disassemble_options = 0) {
38 std::vector<uint32_t> optimized_bin;
39 context->module()->ToBinary(&optimized_bin, true);
40 spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2;
41 SpirvTools tools(target_env);
42 std::string optimized_asm;
43 EXPECT_TRUE(
44 tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options))
45 << "Disassembling failed for shader:\n"
46 << original << std::endl;
47 return optimized_asm;
48 }
49
Match(const std::string & original,IRContext * context,uint32_t disassemble_options=0)50 void Match(const std::string& original, IRContext* context,
51 uint32_t disassemble_options = 0) {
52 std::string disassembly = Disassemble(original, context, disassemble_options);
53 auto match_result = effcee::Match(disassembly, original);
54 EXPECT_EQ(effcee::Result::Status::Ok, match_result.status())
55 << match_result.message() << "\nChecking result:\n"
56 << disassembly;
57 }
58
59 template <class ResultType>
60 struct InstructionFoldingCase {
InstructionFoldingCasespvtools::opt::__anonb0a5c4000111::InstructionFoldingCase61 InstructionFoldingCase(const std::string& tb, uint32_t id, ResultType result)
62 : test_body(tb), id_to_fold(id), expected_result(result) {}
63
64 std::string test_body;
65 uint32_t id_to_fold;
66 ResultType expected_result;
67 };
68
GetInstructionToFold(const std::string test_body,const uint32_t id_to_fold,spv_target_env spv_env)69 std::tuple<std::unique_ptr<IRContext>, Instruction*> GetInstructionToFold(
70 const std::string test_body, const uint32_t id_to_fold,
71 spv_target_env spv_env) {
72 // Build module.
73 std::unique_ptr<IRContext> context =
74 BuildModule(spv_env, nullptr, test_body,
75 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
76 EXPECT_NE(nullptr, context);
77 if (context == nullptr) {
78 return {nullptr, nullptr};
79 }
80
81 // Fold the instruction to test.
82 if (id_to_fold != 0) {
83 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
84 Instruction* inst = def_use_mgr->GetDef(id_to_fold);
85 return {std::move(context), inst};
86 }
87
88 // If there is not ID, we get the instruction just before a terminator
89 // instruction. That could be a return or abort. This is used for cases where
90 // the instruction we want to fold does not have a result id.
91 Function* func = &*context->module()->begin();
92 for (auto& bb : *func) {
93 Instruction* terminator = bb.terminator();
94 if (terminator->IsReturnOrAbort()) {
95 return {std::move(context), terminator->PreviousNode()};
96 }
97 }
98 return {nullptr, nullptr};
99 }
100
FoldInstruction(const std::string test_body,const uint32_t id_to_fold,spv_target_env spv_env)101 std::tuple<std::unique_ptr<IRContext>, Instruction*> FoldInstruction(
102 const std::string test_body, const uint32_t id_to_fold,
103 spv_target_env spv_env) {
104 // Build module.
105 std::unique_ptr<IRContext> context;
106 Instruction* inst = nullptr;
107 std::tie(context, inst) =
108 GetInstructionToFold(test_body, id_to_fold, spv_env);
109
110 if (context == nullptr) {
111 return {nullptr, nullptr};
112 }
113
114 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
115 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
116 EXPECT_EQ(inst->result_id(), original_inst->result_id());
117 EXPECT_EQ(inst->type_id(), original_inst->type_id());
118
119 if (!succeeded && inst != nullptr) {
120 EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
121 for (uint32_t i = 0; i < inst->NumInOperands(); ++i) {
122 EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i));
123 }
124 }
125
126 return {std::move(context), succeeded ? inst : nullptr};
127 }
128
129 template <class ElementType, class Function>
CheckForExpectedScalarConstant(Instruction * inst,ElementType expected_result,Function GetValue)130 void CheckForExpectedScalarConstant(Instruction* inst,
131 ElementType expected_result,
132 Function GetValue) {
133 ASSERT_TRUE(inst);
134
135 IRContext* context = inst->context();
136 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
137 while (inst->opcode() == spv::Op::OpCopyObject) {
138 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
139 }
140
141 // Make sure we have a constant.
142 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
143 const analysis::Constant* constant = const_mrg->GetConstantFromInst(inst);
144 ASSERT_TRUE(constant);
145
146 // Make sure the constant is a scalar.
147 const analysis::ScalarConstant* result = constant->AsScalarConstant();
148 ASSERT_TRUE(result);
149
150 // Check if the result matches the expected value.
151 // If ExpectedType is not a float type, it should cast the value to a double
152 // and never get a nan.
153 if (!std::isnan(static_cast<double>(expected_result))) {
154 EXPECT_EQ(expected_result, GetValue(result));
155 } else {
156 EXPECT_TRUE(std::isnan(static_cast<double>(GetValue(result))));
157 }
158 }
159
160 template <class ElementType, class Function>
CheckForExpectedVectorConstant(Instruction * inst,std::vector<ElementType> expected_result,Function GetValue)161 void CheckForExpectedVectorConstant(Instruction* inst,
162 std::vector<ElementType> expected_result,
163 Function GetValue) {
164 ASSERT_TRUE(inst);
165
166 IRContext* context = inst->context();
167 EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
168 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
169 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
170 std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
171 EXPECT_THAT(opcodes, Contains(inst->opcode()));
172 analysis::ConstantManager* const_mrg = context->get_constant_mgr();
173 const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
174 EXPECT_NE(result, nullptr);
175 if (result != nullptr) {
176 const std::vector<const analysis::Constant*>& componenets =
177 result->AsVectorConstant()->GetComponents();
178 EXPECT_EQ(componenets.size(), expected_result.size());
179 for (size_t i = 0; i < componenets.size(); i++) {
180 EXPECT_EQ(expected_result[i], GetValue(componenets[i]));
181 }
182 }
183 }
184
185 using IntegerInstructionFoldingTest =
186 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
187
TEST_P(IntegerInstructionFoldingTest,Case)188 TEST_P(IntegerInstructionFoldingTest, Case) {
189 const auto& tc = GetParam();
190
191 std::unique_ptr<IRContext> context;
192 Instruction* inst;
193 std::tie(context, inst) =
194 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
195 CheckForExpectedScalarConstant(
196 inst, tc.expected_result, [](const analysis::Constant* c) {
197 return c->AsScalarConstant()->GetU32BitValue();
198 });
199 }
200
201 // Returns a common SPIR-V header for all of the test that follow.
202 #define INT_0_ID 100
203 #define TRUE_ID 101
204 #define VEC2_0_ID 102
205 #define INT_7_ID 103
206 #define FLOAT_0_ID 104
207 #define DOUBLE_0_ID 105
208 #define VEC4_0_ID 106
209 #define DVEC4_0_ID 106
210 #define HALF_0_ID 108
Header()211 const std::string& Header() {
212 static const std::string header = R"(OpCapability Shader
213 OpCapability Float16
214 OpCapability Float64
215 OpCapability Int8
216 OpCapability Int16
217 OpCapability Int64
218 OpCapability CooperativeMatrixKHR
219 OpExtension "SPV_KHR_cooperative_matrix"
220 %1 = OpExtInstImport "GLSL.std.450"
221 OpMemoryModel Logical GLSL450
222 OpEntryPoint Fragment %main "main"
223 OpExecutionMode %main OriginUpperLeft
224 OpSource GLSL 140
225 OpName %main "main"
226 %void = OpTypeVoid
227 %void_func = OpTypeFunction %void
228 %bool = OpTypeBool
229 %float = OpTypeFloat 32
230 %double = OpTypeFloat 64
231 %half = OpTypeFloat 16
232 %101 = OpConstantTrue %bool ; Need a def with an numerical id to define id maps.
233 %true = OpConstantTrue %bool
234 %false = OpConstantFalse %bool
235 %bool_null = OpConstantNull %bool
236 %short = OpTypeInt 16 1
237 %ushort = OpTypeInt 16 0
238 %byte = OpTypeInt 8 1
239 %ubyte = OpTypeInt 8 0
240 %int = OpTypeInt 32 1
241 %long = OpTypeInt 64 1
242 %uint = OpTypeInt 32 0
243 %ulong = OpTypeInt 64 0
244 %v2int = OpTypeVector %int 2
245 %v4int = OpTypeVector %int 4
246 %v2short = OpTypeVector %short 2
247 %v2long = OpTypeVector %long 2
248 %v4long = OpTypeVector %long 4
249 %v4float = OpTypeVector %float 4
250 %v4double = OpTypeVector %double 4
251 %v2uint = OpTypeVector %uint 2
252 %v2ulong = OpTypeVector %ulong 2
253 %v2float = OpTypeVector %float 2
254 %v2double = OpTypeVector %double 2
255 %v2half = OpTypeVector %half 2
256 %v2bool = OpTypeVector %bool 2
257 %m2x2int = OpTypeMatrix %v2int 2
258 %mat4v2float = OpTypeMatrix %v2float 4
259 %mat2v4float = OpTypeMatrix %v4float 2
260 %mat4v4float = OpTypeMatrix %v4float 4
261 %mat4v4double = OpTypeMatrix %v4double 4
262 %struct_v2int_int_int = OpTypeStruct %v2int %int %int
263 %_ptr_int = OpTypePointer Function %int
264 %_ptr_uint = OpTypePointer Function %uint
265 %_ptr_bool = OpTypePointer Function %bool
266 %_ptr_float = OpTypePointer Function %float
267 %_ptr_double = OpTypePointer Function %double
268 %_ptr_half = OpTypePointer Function %half
269 %_ptr_long = OpTypePointer Function %long
270 %_ptr_ulong = OpTypePointer Function %ulong
271 %_ptr_v2int = OpTypePointer Function %v2int
272 %_ptr_v4int = OpTypePointer Function %v4int
273 %_ptr_v4float = OpTypePointer Function %v4float
274 %_ptr_v4double = OpTypePointer Function %v4double
275 %_ptr_struct_v2int_int_int = OpTypePointer Function %struct_v2int_int_int
276 %_ptr_v2float = OpTypePointer Function %v2float
277 %_ptr_v2double = OpTypePointer Function %v2double
278 %int_2 = OpConstant %int 2
279 %int_arr_2 = OpTypeArray %int %int_2
280 %short_0 = OpConstant %short 0
281 %short_2 = OpConstant %short 2
282 %short_3 = OpConstant %short 3
283 %short_n5 = OpConstant %short -5
284 %ubyte_1 = OpConstant %ubyte 1
285 %byte_n1 = OpConstant %byte -1
286 %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps.
287 %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps.
288 %int_0 = OpConstant %int 0
289 %int_1 = OpConstant %int 1
290 %int_3 = OpConstant %int 3
291 %int_4 = OpConstant %int 4
292 %int_10 = OpConstant %int 10
293 %int_1073741824 = OpConstant %int 1073741824
294 %int_n1 = OpConstant %int -1
295 %int_n24 = OpConstant %int -24
296 %int_n858993459 = OpConstant %int -858993459
297 %int_min = OpConstant %int -2147483648
298 %int_max = OpConstant %int 2147483647
299 %long_0 = OpConstant %long 0
300 %long_1 = OpConstant %long 1
301 %long_2 = OpConstant %long 2
302 %long_3 = OpConstant %long 3
303 %long_n3 = OpConstant %long -3
304 %long_7 = OpConstant %long 7
305 %long_n7 = OpConstant %long -7
306 %long_10 = OpConstant %long 10
307 %long_32768 = OpConstant %long 32768
308 %long_n57344 = OpConstant %long -57344
309 %long_n4611686018427387904 = OpConstant %long -4611686018427387904
310 %long_4611686018427387904 = OpConstant %long 4611686018427387904
311 %long_n1 = OpConstant %long -1
312 %long_n3689348814741910323 = OpConstant %long -3689348814741910323
313 %long_min = OpConstant %long -9223372036854775808
314 %long_max = OpConstant %long 9223372036854775807
315 %ulong_7 = OpConstant %ulong 7
316 %ulong_4611686018427387904 = OpConstant %ulong 4611686018427387904
317 %uint_0 = OpConstant %uint 0
318 %uint_1 = OpConstant %uint 1
319 %uint_2 = OpConstant %uint 2
320 %uint_3 = OpConstant %uint 3
321 %uint_4 = OpConstant %uint 4
322 %uint_32 = OpConstant %uint 32
323 %uint_42 = OpConstant %uint 42
324 %uint_2147483649 = OpConstant %uint 2147483649
325 %uint_max = OpConstant %uint 4294967295
326 %ulong_0 = OpConstant %ulong 0
327 %ulong_1 = OpConstant %ulong 1
328 %ulong_2 = OpConstant %ulong 2
329 %ulong_9223372036854775809 = OpConstant %ulong 9223372036854775809
330 %ulong_max = OpConstant %ulong 18446744073709551615
331 %v2int_undef = OpUndef %v2int
332 %v2int_0_0 = OpConstantComposite %v2int %int_0 %int_0
333 %v2int_1_0 = OpConstantComposite %v2int %int_1 %int_0
334 %v2int_2_2 = OpConstantComposite %v2int %int_2 %int_2
335 %v2int_2_3 = OpConstantComposite %v2int %int_2 %int_3
336 %v2int_3_2 = OpConstantComposite %v2int %int_3 %int_2
337 %v2int_n1_n24 = OpConstantComposite %v2int %int_n1 %int_n24
338 %v2int_4_4 = OpConstantComposite %v2int %int_4 %int_4
339 %v2int_min_max = OpConstantComposite %v2int %int_min %int_max
340 %v2short_2_n5 = OpConstantComposite %v2short %short_2 %short_n5
341 %v2long_2_2 = OpConstantComposite %v2long %long_2 %long_2
342 %v2long_2_3 = OpConstantComposite %v2long %long_2 %long_3
343 %v2bool_null = OpConstantNull %v2bool
344 %v2bool_true_false = OpConstantComposite %v2bool %true %false
345 %v2bool_false_true = OpConstantComposite %v2bool %false %true
346 %struct_v2int_int_int_null = OpConstantNull %struct_v2int_int_int
347 %v2int_null = OpConstantNull %v2int
348 %102 = OpConstantComposite %v2int %103 %103
349 %v4int_undef = OpUndef %v4int
350 %v4int_0_0_0_0 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0
351 %m2x2int_undef = OpUndef %m2x2int
352 %struct_undef_0_0 = OpConstantComposite %struct_v2int_int_int %v2int_undef %int_0 %int_0
353 %float_n1 = OpConstant %float -1
354 %104 = OpConstant %float 0 ; Need a def with an numerical id to define id maps.
355 %float_null = OpConstantNull %float
356 %float_0 = OpConstant %float 0
357 %float_n0 = OpConstant %float -0.0
358 %float_1 = OpConstant %float 1
359 %float_2 = OpConstant %float 2
360 %float_3 = OpConstant %float 3
361 %float_4 = OpConstant %float 4
362 %float_2049 = OpConstant %float 2049
363 %float_n2049 = OpConstant %float -2049
364 %float_0p5 = OpConstant %float 0.5
365 %float_0p2 = OpConstant %float 0.2
366 %float_pi = OpConstant %float 1.5555
367 %float_1e16 = OpConstant %float 1e16
368 %float_n1e16 = OpConstant %float -1e16
369 %float_1en16 = OpConstant %float 1e-16
370 %float_n1en16 = OpConstant %float -1e-16
371 %v2float_0_0 = OpConstantComposite %v2float %float_0 %float_0
372 %v2float_2_2 = OpConstantComposite %v2float %float_2 %float_2
373 %v2float_2_3 = OpConstantComposite %v2float %float_2 %float_3
374 %v2float_3_2 = OpConstantComposite %v2float %float_3 %float_2
375 %v2float_4_4 = OpConstantComposite %v2float %float_4 %float_4
376 %v2float_2_0p5 = OpConstantComposite %v2float %float_2 %float_0p5
377 %v2float_0p2_0p5 = OpConstantComposite %v2float %float_0p2 %float_0p5
378 %v2float_null = OpConstantNull %v2float
379 %double_n1 = OpConstant %double -1
380 %105 = OpConstant %double 0 ; Need a def with an numerical id to define id maps.
381 %double_null = OpConstantNull %double
382 %double_0 = OpConstant %double 0
383 %double_n0 = OpConstant %double -0.0
384 %double_1 = OpConstant %double 1
385 %double_2 = OpConstant %double 2
386 %double_3 = OpConstant %double 3
387 %double_4 = OpConstant %double 4
388 %double_5 = OpConstant %double 5
389 %double_0p5 = OpConstant %double 0.5
390 %double_0p2 = OpConstant %double 0.2
391 %v2double_0_0 = OpConstantComposite %v2double %double_0 %double_0
392 %v2double_2_2 = OpConstantComposite %v2double %double_2 %double_2
393 %v2double_2_3 = OpConstantComposite %v2double %double_2 %double_3
394 %v2double_3_2 = OpConstantComposite %v2double %double_3 %double_2
395 %v2double_4_4 = OpConstantComposite %v2double %double_4 %double_4
396 %v2double_2_0p5 = OpConstantComposite %v2double %double_2 %double_0p5
397 %v2double_null = OpConstantNull %v2double
398 %108 = OpConstant %half 0
399 %half_1 = OpConstant %half 1
400 %half_2 = OpConstant %half 2
401 %half_0_1 = OpConstantComposite %v2half %108 %half_1
402 %106 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
403 %v4float_0_0_0_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
404 %v4float_0_0_0_1 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1
405 %v4float_0_1_0_0 = OpConstantComposite %v4float %float_0 %float_1 %float_null %float_0
406 %v4float_1_1_1_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
407 %v4float_1_2_3_4 = OpConstantComposite %v4float %float_1 %float_2 %float_3 %float_4
408 %v4float_null = OpConstantNull %v4float
409 %mat2v4float_null = OpConstantNull %mat2v4float
410 %mat4v4float_null = OpConstantNull %mat4v4float
411 %mat4v4float_1_2_3_4 = OpConstantComposite %mat4v4float %v4float_1_2_3_4 %v4float_1_2_3_4 %v4float_1_2_3_4 %v4float_1_2_3_4
412 %mat4v4float_1_2_3_4_null = OpConstantComposite %mat4v4float %v4float_1_2_3_4 %v4float_null %v4float_1_2_3_4 %v4float_null
413 %107 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
414 %v4double_0_0_0_0 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0
415 %v4double_0_0_0_1 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_1
416 %v4double_0_1_0_0 = OpConstantComposite %v4double %double_0 %double_1 %double_null %double_0
417 %v4double_1_1_1_1 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_1
418 %v4double_1_2_3_4 = OpConstantComposite %v4double %double_1 %double_2 %double_3 %double_4
419 %v4double_1_1_1_0p5 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_0p5
420 %v4double_null = OpConstantNull %v4double
421 %mat4v4double_null = OpConstantNull %mat4v4double
422 %mat4v4double_1_2_3_4 = OpConstantComposite %mat4v4double %v4double_1_2_3_4 %v4double_1_2_3_4 %v4double_1_2_3_4 %v4double_1_2_3_4
423 %mat4v4double_1_2_3_4_null = OpConstantComposite %mat4v4double %v4double_1_2_3_4 %v4double_null %v4double_1_2_3_4 %v4double_null
424 %v4float_n1_2_1_3 = OpConstantComposite %v4float %float_n1 %float_2 %float_1 %float_3
425 %uint_0x3f800000 = OpConstant %uint 0x3f800000
426 %uint_0xbf800000 = OpConstant %uint 0xbf800000
427 %v2uint_0x3f800000_0xbf800000 = OpConstantComposite %v2uint %uint_0x3f800000 %uint_0xbf800000
428 %long_0xbf8000003f800000 = OpConstant %long 0xbf8000003f800000
429 %int_0x3FF00000 = OpConstant %int 0x3FF00000
430 %int_0x00000000 = OpConstant %int 0x00000000
431 %int_0xC05FD666 = OpConstant %int 0xC05FD666
432 %int_0x66666666 = OpConstant %int 0x66666666
433 %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666 = OpConstantComposite %v4int %int_0x00000000 %int_0x3FF00000 %int_0x66666666 %int_0xC05FD666
434 %ushort_0x4400 = OpConstant %ushort 0x4400
435 %short_0x4400 = OpConstant %short 0x4400
436 %ushort_0xBC00 = OpConstant %ushort 0xBC00
437 %short_0xBC00 = OpConstant %short 0xBC00
438 %int_arr_2_undef = OpUndef %int_arr_2
439 %int_coop_matrix = OpTypeCooperativeMatrixKHR %int %uint_3 %uint_3 %uint_32 %uint_0
440 %undef_int_coop_matrix = OpUndef %int_coop_matrix
441 %uint_coop_matrix = OpTypeCooperativeMatrixKHR %uint %uint_3 %uint_3 %uint_32 %uint_0
442 %undef_uint_coop_matrix = OpUndef %uint_coop_matrix
443 %float_coop_matrix = OpTypeCooperativeMatrixKHR %float %uint_3 %uint_3 %uint_32 %uint_0
444 %undef_float_coop_matrix = OpUndef %float_coop_matrix
445 )";
446
447 return header;
448 }
449
450 // Returns the header with definitions of float NaN and double NaN. Since FC
451 // "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" finds
452 // %double_nan = OpConstant %double -0x1.8p+1024 instead of
453 // %double_n0 = OpConstant %double -0,
454 // we separates those definitions from Header().
HeaderWithNaN()455 const std::string& HeaderWithNaN() {
456 static const std::string headerWithNaN =
457 Header() +
458 R"(%float_nan = OpConstant %float -0x1.8p+128
459 %double_nan = OpConstant %double -0x1.8p+1024
460 )";
461
462 return headerWithNaN;
463 }
464
465 // clang-format off
466 INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTest,
467 ::testing::Values(
468 // Test case 0: fold 0*n
469 InstructionFoldingCase<uint32_t>(
470 Header() + "%main = OpFunction %void None %void_func\n" +
471 "%main_lab = OpLabel\n" +
472 "%n = OpVariable %_ptr_int Function\n" +
473 "%load = OpLoad %int %n\n" +
474 "%2 = OpIMul %int %int_0 %load\n" +
475 "OpReturn\n" +
476 "OpFunctionEnd",
477 2, 0),
478 // Test case 1: fold n*0
479 InstructionFoldingCase<uint32_t>(
480 Header() + "%main = OpFunction %void None %void_func\n" +
481 "%main_lab = OpLabel\n" +
482 "%n = OpVariable %_ptr_int Function\n" +
483 "%load = OpLoad %int %n\n" +
484 "%2 = OpIMul %int %load %int_0\n" +
485 "OpReturn\n" +
486 "OpFunctionEnd",
487 2, 0),
488 // Test case 2: fold 0/n (signed)
489 InstructionFoldingCase<uint32_t>(
490 Header() + "%main = OpFunction %void None %void_func\n" +
491 "%main_lab = OpLabel\n" +
492 "%n = OpVariable %_ptr_int Function\n" +
493 "%load = OpLoad %int %n\n" +
494 "%2 = OpSDiv %int %int_0 %load\n" +
495 "OpReturn\n" +
496 "OpFunctionEnd",
497 2, 0),
498 // Test case 3: fold n/0 (signed)
499 InstructionFoldingCase<uint32_t>(
500 Header() + "%main = OpFunction %void None %void_func\n" +
501 "%main_lab = OpLabel\n" +
502 "%n = OpVariable %_ptr_int Function\n" +
503 "%load = OpLoad %int %n\n" +
504 "%2 = OpSDiv %int %load %int_0\n" +
505 "OpReturn\n" +
506 "OpFunctionEnd",
507 2, 0),
508 // Test case 4: fold 0/n (unsigned)
509 InstructionFoldingCase<uint32_t>(
510 Header() + "%main = OpFunction %void None %void_func\n" +
511 "%main_lab = OpLabel\n" +
512 "%n = OpVariable %_ptr_uint Function\n" +
513 "%load = OpLoad %uint %n\n" +
514 "%2 = OpUDiv %uint %uint_0 %load\n" +
515 "OpReturn\n" +
516 "OpFunctionEnd",
517 2, 0),
518 // Test case 5: fold n/0 (unsigned)
519 InstructionFoldingCase<uint32_t>(
520 Header() + "%main = OpFunction %void None %void_func\n" +
521 "%main_lab = OpLabel\n" +
522 "%n = OpVariable %_ptr_int Function\n" +
523 "%load = OpLoad %int %n\n" +
524 "%2 = OpSDiv %int %load %int_0\n" +
525 "OpReturn\n" +
526 "OpFunctionEnd",
527 2, 0),
528 // Test case 6: fold 0 remainder n
529 InstructionFoldingCase<uint32_t>(
530 Header() + "%main = OpFunction %void None %void_func\n" +
531 "%main_lab = OpLabel\n" +
532 "%n = OpVariable %_ptr_int Function\n" +
533 "%load = OpLoad %int %n\n" +
534 "%2 = OpSRem %int %int_0 %load\n" +
535 "OpReturn\n" +
536 "OpFunctionEnd",
537 2, 0),
538 // Test case 7: fold n remainder 0
539 InstructionFoldingCase<uint32_t>(
540 Header() + "%main = OpFunction %void None %void_func\n" +
541 "%main_lab = OpLabel\n" +
542 "%n = OpVariable %_ptr_int Function\n" +
543 "%load = OpLoad %int %n\n" +
544 "%2 = OpSRem %int %load %int_0\n" +
545 "OpReturn\n" +
546 "OpFunctionEnd",
547 2, 0),
548 // Test case 8: fold 0%n (signed)
549 InstructionFoldingCase<uint32_t>(
550 Header() + "%main = OpFunction %void None %void_func\n" +
551 "%main_lab = OpLabel\n" +
552 "%n = OpVariable %_ptr_int Function\n" +
553 "%load = OpLoad %int %n\n" +
554 "%2 = OpSMod %int %int_0 %load\n" +
555 "OpReturn\n" +
556 "OpFunctionEnd",
557 2, 0),
558 // Test case 9: fold n%0 (signed)
559 InstructionFoldingCase<uint32_t>(
560 Header() + "%main = OpFunction %void None %void_func\n" +
561 "%main_lab = OpLabel\n" +
562 "%n = OpVariable %_ptr_int Function\n" +
563 "%load = OpLoad %int %n\n" +
564 "%2 = OpSMod %int %load %int_0\n" +
565 "OpReturn\n" +
566 "OpFunctionEnd",
567 2, 0),
568 // Test case 10: fold 0%n (unsigned)
569 InstructionFoldingCase<uint32_t>(
570 Header() + "%main = OpFunction %void None %void_func\n" +
571 "%main_lab = OpLabel\n" +
572 "%n = OpVariable %_ptr_uint Function\n" +
573 "%load = OpLoad %uint %n\n" +
574 "%2 = OpUMod %uint %uint_0 %load\n" +
575 "OpReturn\n" +
576 "OpFunctionEnd",
577 2, 0),
578 // Test case 11: fold n%0 (unsigned)
579 InstructionFoldingCase<uint32_t>(
580 Header() + "%main = OpFunction %void None %void_func\n" +
581 "%main_lab = OpLabel\n" +
582 "%n = OpVariable %_ptr_uint Function\n" +
583 "%load = OpLoad %uint %n\n" +
584 "%2 = OpUMod %uint %load %uint_0\n" +
585 "OpReturn\n" +
586 "OpFunctionEnd",
587 2, 0),
588 // Test case 12: fold n << 32
589 InstructionFoldingCase<uint32_t>(
590 Header() + "%main = OpFunction %void None %void_func\n" +
591 "%main_lab = OpLabel\n" +
592 "%n = OpVariable %_ptr_uint Function\n" +
593 "%load = OpLoad %uint %n\n" +
594 "%2 = OpShiftLeftLogical %uint %load %uint_32\n" +
595 "OpReturn\n" +
596 "OpFunctionEnd",
597 2, 0),
598 // Test case 13: fold n >> 32
599 InstructionFoldingCase<uint32_t>(
600 Header() + "%main = OpFunction %void None %void_func\n" +
601 "%main_lab = OpLabel\n" +
602 "%n = OpVariable %_ptr_uint Function\n" +
603 "%load = OpLoad %uint %n\n" +
604 "%2 = OpShiftRightLogical %uint %load %uint_32\n" +
605 "OpReturn\n" +
606 "OpFunctionEnd",
607 2, 0),
608 // Test case 14: fold n | 0xFFFFFFFF
609 InstructionFoldingCase<uint32_t>(
610 Header() + "%main = OpFunction %void None %void_func\n" +
611 "%main_lab = OpLabel\n" +
612 "%n = OpVariable %_ptr_uint Function\n" +
613 "%load = OpLoad %uint %n\n" +
614 "%2 = OpBitwiseOr %uint %load %uint_max\n" +
615 "OpReturn\n" +
616 "OpFunctionEnd",
617 2, 0xFFFFFFFF),
618 // Test case 15: fold 0xFFFFFFFF | n
619 InstructionFoldingCase<uint32_t>(
620 Header() + "%main = OpFunction %void None %void_func\n" +
621 "%main_lab = OpLabel\n" +
622 "%n = OpVariable %_ptr_uint Function\n" +
623 "%load = OpLoad %uint %n\n" +
624 "%2 = OpBitwiseOr %uint %uint_max %load\n" +
625 "OpReturn\n" +
626 "OpFunctionEnd",
627 2, 0xFFFFFFFF),
628 // Test case 16: fold n & 0
629 InstructionFoldingCase<uint32_t>(
630 Header() + "%main = OpFunction %void None %void_func\n" +
631 "%main_lab = OpLabel\n" +
632 "%n = OpVariable %_ptr_uint Function\n" +
633 "%load = OpLoad %uint %n\n" +
634 "%2 = OpBitwiseAnd %uint %load %uint_0\n" +
635 "OpReturn\n" +
636 "OpFunctionEnd",
637 2, 0),
638 // Test case 17: fold 1/0 (signed)
639 InstructionFoldingCase<uint32_t>(
640 Header() + "%main = OpFunction %void None %void_func\n" +
641 "%main_lab = OpLabel\n" +
642 "%2 = OpSDiv %int %int_1 %int_0\n" +
643 "OpReturn\n" +
644 "OpFunctionEnd",
645 2, 0),
646 // Test case 18: fold 1/0 (unsigned)
647 InstructionFoldingCase<uint32_t>(
648 Header() + "%main = OpFunction %void None %void_func\n" +
649 "%main_lab = OpLabel\n" +
650 "%2 = OpUDiv %uint %uint_1 %uint_0\n" +
651 "OpReturn\n" +
652 "OpFunctionEnd",
653 2, 0),
654 // Test case 19: fold OpSRem 1 0 (signed)
655 InstructionFoldingCase<uint32_t>(
656 Header() + "%main = OpFunction %void None %void_func\n" +
657 "%main_lab = OpLabel\n" +
658 "%2 = OpSRem %int %int_1 %int_0\n" +
659 "OpReturn\n" +
660 "OpFunctionEnd",
661 2, 0),
662 // Test case 20: fold 1%0 (signed)
663 InstructionFoldingCase<uint32_t>(
664 Header() + "%main = OpFunction %void None %void_func\n" +
665 "%main_lab = OpLabel\n" +
666 "%2 = OpSMod %int %int_1 %int_0\n" +
667 "OpReturn\n" +
668 "OpFunctionEnd",
669 2, 0),
670 // Test case 21: fold 1%0 (unsigned)
671 InstructionFoldingCase<uint32_t>(
672 Header() + "%main = OpFunction %void None %void_func\n" +
673 "%main_lab = OpLabel\n" +
674 "%2 = OpUMod %uint %uint_1 %uint_0\n" +
675 "OpReturn\n" +
676 "OpFunctionEnd",
677 2, 0),
678 // Test case 22: fold unsigned n >> 42 (undefined, so set to zero).
679 InstructionFoldingCase<uint32_t>(
680 Header() + "%main = OpFunction %void None %void_func\n" +
681 "%main_lab = OpLabel\n" +
682 "%n = OpVariable %_ptr_uint Function\n" +
683 "%load = OpLoad %uint %n\n" +
684 "%2 = OpShiftRightLogical %uint %load %uint_42\n" +
685 "OpReturn\n" +
686 "OpFunctionEnd",
687 2, 0),
688 // Test case 23: fold signed n >> 42 (undefined, so set to zero).
689 InstructionFoldingCase<uint32_t>(
690 Header() + "%main = OpFunction %void None %void_func\n" +
691 "%main_lab = OpLabel\n" +
692 "%n = OpVariable %_ptr_int Function\n" +
693 "%load = OpLoad %int %n\n" +
694 "%2 = OpShiftRightLogical %int %load %uint_42\n" +
695 "OpReturn\n" +
696 "OpFunctionEnd",
697 2, 0),
698 // Test case 24: fold n << 42 (undefined, so set to zero).
699 InstructionFoldingCase<uint32_t>(
700 Header() + "%main = OpFunction %void None %void_func\n" +
701 "%main_lab = OpLabel\n" +
702 "%n = OpVariable %_ptr_int Function\n" +
703 "%load = OpLoad %int %n\n" +
704 "%2 = OpShiftLeftLogical %int %load %uint_42\n" +
705 "OpReturn\n" +
706 "OpFunctionEnd",
707 2, 0),
708 // Test case 25: fold -24 >> 32 (defined as -1)
709 InstructionFoldingCase<uint32_t>(
710 Header() + "%main = OpFunction %void None %void_func\n" +
711 "%main_lab = OpLabel\n" +
712 "%2 = OpShiftRightArithmetic %int %int_n24 %uint_32\n" +
713 "OpReturn\n" +
714 "OpFunctionEnd",
715 2, -1),
716 // Test case 26: fold 2 >> 32 (signed)
717 InstructionFoldingCase<uint32_t>(
718 Header() + "%main = OpFunction %void None %void_func\n" +
719 "%main_lab = OpLabel\n" +
720 "%2 = OpShiftRightArithmetic %int %int_2 %uint_32\n" +
721 "OpReturn\n" +
722 "OpFunctionEnd",
723 2, 0),
724 // Test case 27: fold 2 >> 32 (unsigned)
725 InstructionFoldingCase<uint32_t>(
726 Header() + "%main = OpFunction %void None %void_func\n" +
727 "%main_lab = OpLabel\n" +
728 "%2 = OpShiftRightLogical %int %int_2 %uint_32\n" +
729 "OpReturn\n" +
730 "OpFunctionEnd",
731 2, 0),
732 // Test case 28: fold 2 << 32
733 InstructionFoldingCase<uint32_t>(
734 Header() + "%main = OpFunction %void None %void_func\n" +
735 "%main_lab = OpLabel\n" +
736 "%2 = OpShiftLeftLogical %int %int_2 %uint_32\n" +
737 "OpReturn\n" +
738 "OpFunctionEnd",
739 2, 0),
740 // Test case 29: fold -INT_MIN
741 InstructionFoldingCase<uint32_t>(
742 Header() + "%main = OpFunction %void None %void_func\n" +
743 "%main_lab = OpLabel\n" +
744 "%2 = OpSNegate %int %int_min\n" +
745 "OpReturn\n" +
746 "OpFunctionEnd",
747 2, std::numeric_limits<int32_t>::min()),
748 // Test case 30: fold UMin 3 4
749 InstructionFoldingCase<uint32_t>(
750 Header() + "%main = OpFunction %void None %void_func\n" +
751 "%main_lab = OpLabel\n" +
752 "%2 = OpExtInst %uint %1 UMin %uint_3 %uint_4\n" +
753 "OpReturn\n" +
754 "OpFunctionEnd",
755 2, 3),
756 // Test case 31: fold UMin 4 2
757 InstructionFoldingCase<uint32_t>(
758 Header() + "%main = OpFunction %void None %void_func\n" +
759 "%main_lab = OpLabel\n" +
760 "%2 = OpExtInst %uint %1 UMin %uint_4 %uint_2\n" +
761 "OpReturn\n" +
762 "OpFunctionEnd",
763 2, 2),
764 // Test case 32: fold SMin 3 4
765 InstructionFoldingCase<uint32_t>(
766 Header() + "%main = OpFunction %void None %void_func\n" +
767 "%main_lab = OpLabel\n" +
768 "%2 = OpExtInst %int %1 UMin %int_3 %int_4\n" +
769 "OpReturn\n" +
770 "OpFunctionEnd",
771 2, 3),
772 // Test case 33: fold SMin 4 2
773 InstructionFoldingCase<uint32_t>(
774 Header() + "%main = OpFunction %void None %void_func\n" +
775 "%main_lab = OpLabel\n" +
776 "%2 = OpExtInst %int %1 SMin %int_4 %int_2\n" +
777 "OpReturn\n" +
778 "OpFunctionEnd",
779 2, 2),
780 // Test case 34: fold UMax 3 4
781 InstructionFoldingCase<uint32_t>(
782 Header() + "%main = OpFunction %void None %void_func\n" +
783 "%main_lab = OpLabel\n" +
784 "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_4\n" +
785 "OpReturn\n" +
786 "OpFunctionEnd",
787 2, 4),
788 // Test case 35: fold UMax 3 2
789 InstructionFoldingCase<uint32_t>(
790 Header() + "%main = OpFunction %void None %void_func\n" +
791 "%main_lab = OpLabel\n" +
792 "%2 = OpExtInst %uint %1 UMax %uint_3 %uint_2\n" +
793 "OpReturn\n" +
794 "OpFunctionEnd",
795 2, 3),
796 // Test case 36: fold SMax 3 4
797 InstructionFoldingCase<uint32_t>(
798 Header() + "%main = OpFunction %void None %void_func\n" +
799 "%main_lab = OpLabel\n" +
800 "%2 = OpExtInst %int %1 UMax %int_3 %int_4\n" +
801 "OpReturn\n" +
802 "OpFunctionEnd",
803 2, 4),
804 // Test case 37: fold SMax 3 2
805 InstructionFoldingCase<uint32_t>(
806 Header() + "%main = OpFunction %void None %void_func\n" +
807 "%main_lab = OpLabel\n" +
808 "%2 = OpExtInst %int %1 SMax %int_3 %int_2\n" +
809 "OpReturn\n" +
810 "OpFunctionEnd",
811 2, 3),
812 // Test case 38: fold UClamp 2 3 4
813 InstructionFoldingCase<uint32_t>(
814 Header() + "%main = OpFunction %void None %void_func\n" +
815 "%main_lab = OpLabel\n" +
816 "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_3 %uint_4\n" +
817 "OpReturn\n" +
818 "OpFunctionEnd",
819 2, 3),
820 // Test case 39: fold UClamp 2 0 4
821 InstructionFoldingCase<uint32_t>(
822 Header() + "%main = OpFunction %void None %void_func\n" +
823 "%main_lab = OpLabel\n" +
824 "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_4\n" +
825 "OpReturn\n" +
826 "OpFunctionEnd",
827 2, 2),
828 // Test case 40: fold UClamp 2 0 1
829 InstructionFoldingCase<uint32_t>(
830 Header() + "%main = OpFunction %void None %void_func\n" +
831 "%main_lab = OpLabel\n" +
832 "%2 = OpExtInst %uint %1 UClamp %uint_2 %uint_0 %uint_1\n" +
833 "OpReturn\n" +
834 "OpFunctionEnd",
835 2, 1),
836 // Test case 41: fold SClamp 2 3 4
837 InstructionFoldingCase<uint32_t>(
838 Header() + "%main = OpFunction %void None %void_func\n" +
839 "%main_lab = OpLabel\n" +
840 "%2 = OpExtInst %int %1 SClamp %int_2 %int_3 %int_4\n" +
841 "OpReturn\n" +
842 "OpFunctionEnd",
843 2, 3),
844 // Test case 42: fold SClamp 2 0 4
845 InstructionFoldingCase<uint32_t>(
846 Header() + "%main = OpFunction %void None %void_func\n" +
847 "%main_lab = OpLabel\n" +
848 "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_4\n" +
849 "OpReturn\n" +
850 "OpFunctionEnd",
851 2, 2),
852 // Test case 43: fold SClamp 2 0 1
853 InstructionFoldingCase<uint32_t>(
854 Header() + "%main = OpFunction %void None %void_func\n" +
855 "%main_lab = OpLabel\n" +
856 "%2 = OpExtInst %int %1 SClamp %int_2 %int_0 %int_1\n" +
857 "OpReturn\n" +
858 "OpFunctionEnd",
859 2, 1),
860 // Test case 44: SClamp 1 2 x
861 InstructionFoldingCase<uint32_t>(
862 Header() + "%main = OpFunction %void None %void_func\n" +
863 "%main_lab = OpLabel\n" +
864 "%undef = OpUndef %int\n" +
865 "%2 = OpExtInst %int %1 SClamp %int_1 %int_2 %undef\n" +
866 "OpReturn\n" +
867 "OpFunctionEnd",
868 2, 2),
869 // Test case 45: SClamp 2 x 1
870 InstructionFoldingCase<uint32_t>(
871 Header() + "%main = OpFunction %void None %void_func\n" +
872 "%main_lab = OpLabel\n" +
873 "%undef = OpUndef %int\n" +
874 "%2 = OpExtInst %int %1 SClamp %int_2 %undef %int_1\n" +
875 "OpReturn\n" +
876 "OpFunctionEnd",
877 2, 1),
878 // Test case 46: UClamp 1 2 x
879 InstructionFoldingCase<uint32_t>(
880 Header() + "%main = OpFunction %void None %void_func\n" +
881 "%main_lab = OpLabel\n" +
882 "%undef = OpUndef %uint\n" +
883 "%2 = OpExtInst %uint %1 UClamp %uint_1 %uint_2 %undef\n" +
884 "OpReturn\n" +
885 "OpFunctionEnd",
886 2, 2),
887 // Test case 47: UClamp 2 x 1
888 InstructionFoldingCase<uint32_t>(
889 Header() + "%main = OpFunction %void None %void_func\n" +
890 "%main_lab = OpLabel\n" +
891 "%undef = OpUndef %uint\n" +
892 "%2 = OpExtInst %uint %1 UClamp %uint_2 %undef %uint_1\n" +
893 "OpReturn\n" +
894 "OpFunctionEnd",
895 2, 1),
896 // Test case 48: Bit-cast int 0 to unsigned int
897 InstructionFoldingCase<uint32_t>(
898 Header() + "%main = OpFunction %void None %void_func\n" +
899 "%main_lab = OpLabel\n" +
900 "%2 = OpBitcast %uint %int_0\n" +
901 "OpReturn\n" +
902 "OpFunctionEnd",
903 2, 0),
904 // Test case 49: Bit-cast int -24 to unsigned int
905 InstructionFoldingCase<uint32_t>(
906 Header() + "%main = OpFunction %void None %void_func\n" +
907 "%main_lab = OpLabel\n" +
908 "%2 = OpBitcast %uint %int_n24\n" +
909 "OpReturn\n" +
910 "OpFunctionEnd",
911 2, static_cast<uint32_t>(-24)),
912 // Test case 50: Bit-cast float 1.0f to unsigned int
913 InstructionFoldingCase<uint32_t>(
914 Header() + "%main = OpFunction %void None %void_func\n" +
915 "%main_lab = OpLabel\n" +
916 "%2 = OpBitcast %uint %float_1\n" +
917 "OpReturn\n" +
918 "OpFunctionEnd",
919 2, static_cast<uint32_t>(0x3f800000)),
920 // Test case 51: Bit-cast ushort 0xBC00 to ushort
921 InstructionFoldingCase<uint32_t>(
922 Header() + "%main = OpFunction %void None %void_func\n" +
923 "%main_lab = OpLabel\n" +
924 "%2 = OpBitcast %ushort %ushort_0xBC00\n" +
925 "OpReturn\n" +
926 "OpFunctionEnd",
927 2, 0xBC00),
928 // Test case 52: Bit-cast short 0xBC00 to ushort
929 InstructionFoldingCase<uint32_t>(
930 Header() + "%main = OpFunction %void None %void_func\n" +
931 "%main_lab = OpLabel\n" +
932 "%2 = OpBitcast %ushort %short_0xBC00\n" +
933 "OpReturn\n" +
934 "OpFunctionEnd",
935 2, 0xBC00),
936 // Test case 53: Bit-cast half 1 to ushort
937 InstructionFoldingCase<uint32_t>(
938 Header() + "%main = OpFunction %void None %void_func\n" +
939 "%main_lab = OpLabel\n" +
940 "%2 = OpBitcast %ushort %half_1\n" +
941 "OpReturn\n" +
942 "OpFunctionEnd",
943 2, 0x3C00),
944 // Test case 54: Bit-cast ushort 0xBC00 to short
945 InstructionFoldingCase<uint32_t>(
946 Header() + "%main = OpFunction %void None %void_func\n" +
947 "%main_lab = OpLabel\n" +
948 "%2 = OpBitcast %short %ushort_0xBC00\n" +
949 "OpReturn\n" +
950 "OpFunctionEnd",
951 2, 0xFFFFBC00),
952 // Test case 55: Bit-cast short 0xBC00 to short
953 InstructionFoldingCase<uint32_t>(
954 Header() + "%main = OpFunction %void None %void_func\n" +
955 "%main_lab = OpLabel\n" +
956 "%2 = OpBitcast %short %short_0xBC00\n" +
957 "OpReturn\n" +
958 "OpFunctionEnd",
959 2, 0xFFFFBC00),
960 // Test case 56: Bit-cast half 1 to short
961 InstructionFoldingCase<uint32_t>(
962 Header() + "%main = OpFunction %void None %void_func\n" +
963 "%main_lab = OpLabel\n" +
964 "%2 = OpBitcast %short %half_1\n" +
965 "OpReturn\n" +
966 "OpFunctionEnd",
967 2, 0x3C00),
968 // Test case 57: Bit-cast ushort 0xBC00 to half
969 InstructionFoldingCase<uint32_t>(
970 Header() + "%main = OpFunction %void None %void_func\n" +
971 "%main_lab = OpLabel\n" +
972 "%2 = OpBitcast %half %ushort_0xBC00\n" +
973 "OpReturn\n" +
974 "OpFunctionEnd",
975 2, 0xBC00),
976 // Test case 58: Bit-cast short 0xBC00 to half
977 InstructionFoldingCase<uint32_t>(
978 Header() + "%main = OpFunction %void None %void_func\n" +
979 "%main_lab = OpLabel\n" +
980 "%2 = OpBitcast %half %short_0xBC00\n" +
981 "OpReturn\n" +
982 "OpFunctionEnd",
983 2, 0xFFFFBC00),
984 // Test case 59: Bit-cast half 1 to half
985 InstructionFoldingCase<uint32_t>(
986 Header() + "%main = OpFunction %void None %void_func\n" +
987 "%main_lab = OpLabel\n" +
988 "%2 = OpBitcast %half %half_1\n" +
989 "OpReturn\n" +
990 "OpFunctionEnd",
991 2, 0x3C00),
992 // Test case 60: Bit-cast ubyte 1 to byte
993 InstructionFoldingCase<uint32_t>(
994 Header() + "%main = OpFunction %void None %void_func\n" +
995 "%main_lab = OpLabel\n" +
996 "%2 = OpBitcast %byte %ubyte_1\n" +
997 "OpReturn\n" +
998 "OpFunctionEnd",
999 2, 1),
1000 // Test case 61: Bit-cast byte -1 to ubyte
1001 InstructionFoldingCase<uint32_t>(
1002 Header() + "%main = OpFunction %void None %void_func\n" +
1003 "%main_lab = OpLabel\n" +
1004 "%2 = OpBitcast %ubyte %byte_n1\n" +
1005 "OpReturn\n" +
1006 "OpFunctionEnd",
1007 2, 0xFF),
1008 // Test case 62: Negate 2.
1009 InstructionFoldingCase<uint32_t>(
1010 Header() + "%main = OpFunction %void None %void_func\n" +
1011 "%main_lab = OpLabel\n" +
1012 "%2 = OpSNegate %int %int_2\n" +
1013 "OpReturn\n" +
1014 "OpFunctionEnd",
1015 2, -2),
1016 // Test case 63: Negate negative short.
1017 InstructionFoldingCase<uint32_t>(
1018 Header() + "%main = OpFunction %void None %void_func\n" +
1019 "%main_lab = OpLabel\n" +
1020 "%2 = OpSNegate %short %short_0xBC00\n" +
1021 "OpReturn\n" +
1022 "OpFunctionEnd",
1023 2, 0x4400 /* expected to be sign extended. */),
1024 // Test case 64: Negate positive short.
1025 InstructionFoldingCase<uint32_t>(
1026 Header() + "%main = OpFunction %void None %void_func\n" +
1027 "%main_lab = OpLabel\n" +
1028 "%2 = OpSNegate %short %short_0x4400\n" +
1029 "OpReturn\n" +
1030 "OpFunctionEnd",
1031 2, 0xFFFFBC00 /* expected to be sign extended. */),
1032 // Test case 65: Negate a negative short.
1033 InstructionFoldingCase<uint32_t>(
1034 Header() + "%main = OpFunction %void None %void_func\n" +
1035 "%main_lab = OpLabel\n" +
1036 "%2 = OpSNegate %ushort %ushort_0xBC00\n" +
1037 "OpReturn\n" +
1038 "OpFunctionEnd",
1039 2, 0x4400 /* expected to be zero extended. */),
1040 // Test case 66: Negate positive short.
1041 InstructionFoldingCase<uint32_t>(
1042 Header() + "%main = OpFunction %void None %void_func\n" +
1043 "%main_lab = OpLabel\n" +
1044 "%2 = OpSNegate %ushort %ushort_0x4400\n" +
1045 "OpReturn\n" +
1046 "OpFunctionEnd",
1047 2, 0xBC00 /* expected to be zero extended. */),
1048 // Test case 67: Fold 2 + 3 (short)
1049 InstructionFoldingCase<uint32_t>(
1050 Header() + "%main = OpFunction %void None %void_func\n" +
1051 "%main_lab = OpLabel\n" +
1052 "%2 = OpIAdd %short %short_2 %short_3\n" +
1053 "OpReturn\n" +
1054 "OpFunctionEnd",
1055 2, 5),
1056 // Test case 68: Fold 2 + -5 (short)
1057 InstructionFoldingCase<uint32_t>(
1058 Header() + "%main = OpFunction %void None %void_func\n" +
1059 "%main_lab = OpLabel\n" +
1060 "%2 = OpIAdd %short %short_2 %short_n5\n" +
1061 "OpReturn\n" +
1062 "OpFunctionEnd",
1063 2, -3),
1064 // Test case 69: Fold int(3ll)
1065 InstructionFoldingCase<uint32_t>(
1066 Header() + "%main = OpFunction %void None %void_func\n" +
1067 "%main_lab = OpLabel\n" +
1068 "%2 = OpSConvert %int %long_3\n" +
1069 "OpReturn\n" +
1070 "OpFunctionEnd",
1071 2, 3),
1072 // Test case 70: Fold short(-3ll)
1073 InstructionFoldingCase<uint32_t>(
1074 Header() + "%main = OpFunction %void None %void_func\n" +
1075 "%main_lab = OpLabel\n" +
1076 "%2 = OpSConvert %short %long_n3\n" +
1077 "OpReturn\n" +
1078 "OpFunctionEnd",
1079 2, -3),
1080 // Test case 71: Fold short(32768ll) - This should do a sign extend when
1081 // converting to short.
1082 InstructionFoldingCase<uint32_t>(
1083 Header() + "%main = OpFunction %void None %void_func\n" +
1084 "%main_lab = OpLabel\n" +
1085 "%2 = OpSConvert %short %long_32768\n" +
1086 "OpReturn\n" +
1087 "OpFunctionEnd",
1088 2, -32768),
1089 // Test case 72: Fold short(-57344) - This should do a sign extend when
1090 // converting to short making the upper bits 0.
1091 InstructionFoldingCase<uint32_t>(
1092 Header() + "%main = OpFunction %void None %void_func\n" +
1093 "%main_lab = OpLabel\n" +
1094 "%2 = OpSConvert %short %long_n57344\n" +
1095 "OpReturn\n" +
1096 "OpFunctionEnd",
1097 2, 8192),
1098 // Test case 73: Fold int(-5(short)). The -5 should be interpreted as an unsigned value, and be zero extended to 32-bits.
1099 InstructionFoldingCase<uint32_t>(
1100 Header() + "%main = OpFunction %void None %void_func\n" +
1101 "%main_lab = OpLabel\n" +
1102 "%2 = OpUConvert %uint %short_n5\n" +
1103 "OpReturn\n" +
1104 "OpFunctionEnd",
1105 2, 65531),
1106 // Test case 74: Fold short(-24(int)). The upper bits should be cleared. So 0xFFFFFFE8 should become 0x0000FFE8.
1107 InstructionFoldingCase<uint32_t>(
1108 Header() + "%main = OpFunction %void None %void_func\n" +
1109 "%main_lab = OpLabel\n" +
1110 "%2 = OpUConvert %ushort %int_n24\n" +
1111 "OpReturn\n" +
1112 "OpFunctionEnd",
1113 2, 65512)
1114 ));
1115 // clang-format on
1116
1117 using LongIntegerInstructionFoldingTest =
1118 ::testing::TestWithParam<InstructionFoldingCase<uint64_t>>;
1119
TEST_P(LongIntegerInstructionFoldingTest,Case)1120 TEST_P(LongIntegerInstructionFoldingTest, Case) {
1121 const auto& tc = GetParam();
1122
1123 std::unique_ptr<IRContext> context;
1124 Instruction* inst;
1125 std::tie(context, inst) =
1126 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1127 CheckForExpectedScalarConstant(
1128 inst, tc.expected_result, [](const analysis::Constant* c) {
1129 return c->AsScalarConstant()->GetU64BitValue();
1130 });
1131 }
1132
1133 INSTANTIATE_TEST_SUITE_P(
1134 TestCase, LongIntegerInstructionFoldingTest,
1135 ::testing::Values(
1136 // Test case 0: fold 1+4611686018427387904
1137 InstructionFoldingCase<uint64_t>(
1138 Header() + "%main = OpFunction %void None %void_func\n" +
1139 "%main_lab = OpLabel\n" +
1140 "%n = OpVariable %_ptr_int Function\n" +
1141 "%load = OpLoad %int %n\n" +
1142 "%2 = OpIAdd %long %long_1 %long_4611686018427387904\n" +
1143 "OpReturn\n" + "OpFunctionEnd",
1144 2, 1 + 4611686018427387904),
1145 // Test case 1: fold 1-4611686018427387904
1146 InstructionFoldingCase<uint64_t>(
1147 Header() + "%main = OpFunction %void None %void_func\n" +
1148 "%main_lab = OpLabel\n" +
1149 "%n = OpVariable %_ptr_int Function\n" +
1150 "%load = OpLoad %int %n\n" +
1151 "%2 = OpISub %long %long_1 %long_4611686018427387904\n" +
1152 "OpReturn\n" + "OpFunctionEnd",
1153 2, 1 - 4611686018427387904),
1154 // Test case 2: fold 2*4611686018427387904
1155 InstructionFoldingCase<uint64_t>(
1156 Header() + "%main = OpFunction %void None %void_func\n" +
1157 "%main_lab = OpLabel\n" +
1158 "%n = OpVariable %_ptr_int Function\n" +
1159 "%load = OpLoad %int %n\n" +
1160 "%2 = OpIMul %long %long_2 %long_4611686018427387904\n" +
1161 "OpReturn\n" + "OpFunctionEnd",
1162 2, 9223372036854775808ull),
1163 // Test case 3: fold 4611686018427387904/2 (unsigned)
1164 InstructionFoldingCase<uint64_t>(
1165 Header() + "%main = OpFunction %void None %void_func\n" +
1166 "%main_lab = OpLabel\n" +
1167 "%n = OpVariable %_ptr_int Function\n" +
1168 "%load = OpLoad %int %n\n" +
1169 "%2 = OpUDiv %ulong %ulong_4611686018427387904 %ulong_2\n" +
1170 "OpReturn\n" + "OpFunctionEnd",
1171 2, 4611686018427387904 / 2),
1172 // Test case 4: fold 4611686018427387904/2 (signed)
1173 InstructionFoldingCase<uint64_t>(
1174 Header() + "%main = OpFunction %void None %void_func\n" +
1175 "%main_lab = OpLabel\n" +
1176 "%n = OpVariable %_ptr_int Function\n" +
1177 "%load = OpLoad %int %n\n" +
1178 "%2 = OpSDiv %long %long_4611686018427387904 %long_2\n" +
1179 "OpReturn\n" + "OpFunctionEnd",
1180 2, 4611686018427387904 / 2),
1181 // Test case 5: fold -4611686018427387904/2 (signed)
1182 InstructionFoldingCase<uint64_t>(
1183 Header() + "%main = OpFunction %void None %void_func\n" +
1184 "%main_lab = OpLabel\n" +
1185 "%n = OpVariable %_ptr_int Function\n" +
1186 "%load = OpLoad %int %n\n" +
1187 "%2 = OpSDiv %long %long_n4611686018427387904 %long_2\n" +
1188 "OpReturn\n" + "OpFunctionEnd",
1189 2, -4611686018427387904 / 2),
1190 // Test case 6: fold 4611686018427387904 mod 7 (unsigned)
1191 InstructionFoldingCase<uint64_t>(
1192 Header() + "%main = OpFunction %void None %void_func\n" +
1193 "%main_lab = OpLabel\n" +
1194 "%n = OpVariable %_ptr_int Function\n" +
1195 "%load = OpLoad %int %n\n" +
1196 "%2 = OpUMod %ulong %ulong_4611686018427387904 %ulong_7\n" +
1197 "OpReturn\n" + "OpFunctionEnd",
1198 2, 4611686018427387904ull % 7ull),
1199 // Test case 7: fold 7 mod 3 (signed)
1200 InstructionFoldingCase<uint64_t>(
1201 Header() + "%main = OpFunction %void None %void_func\n" +
1202 "%main_lab = OpLabel\n" +
1203 "%n = OpVariable %_ptr_int Function\n" +
1204 "%load = OpLoad %int %n\n" +
1205 "%2 = OpSMod %long %long_7 %long_3\n" + "OpReturn\n" +
1206 "OpFunctionEnd",
1207 2, 1ull),
1208 // Test case 8: fold 7 rem 3 (signed)
1209 InstructionFoldingCase<uint64_t>(
1210 Header() + "%main = OpFunction %void None %void_func\n" +
1211 "%main_lab = OpLabel\n" +
1212 "%n = OpVariable %_ptr_int Function\n" +
1213 "%load = OpLoad %int %n\n" +
1214 "%2 = OpSRem %long %long_7 %long_3\n" + "OpReturn\n" +
1215 "OpFunctionEnd",
1216 2, 1ull),
1217 // Test case 9: fold 7 mod -3 (signed)
1218 InstructionFoldingCase<uint64_t>(
1219 Header() + "%main = OpFunction %void None %void_func\n" +
1220 "%main_lab = OpLabel\n" +
1221 "%n = OpVariable %_ptr_int Function\n" +
1222 "%load = OpLoad %int %n\n" +
1223 "%2 = OpSMod %long %long_7 %long_n3\n" + "OpReturn\n" +
1224 "OpFunctionEnd",
1225 2, -2ll),
1226 // Test case 10: fold 7 rem 3 (signed)
1227 InstructionFoldingCase<uint64_t>(
1228 Header() + "%main = OpFunction %void None %void_func\n" +
1229 "%main_lab = OpLabel\n" +
1230 "%n = OpVariable %_ptr_int Function\n" +
1231 "%load = OpLoad %int %n\n" +
1232 "%2 = OpSRem %long %long_7 %long_n3\n" + "OpReturn\n" +
1233 "OpFunctionEnd",
1234 2, 1ll),
1235 // Test case 11: fold -7 mod 3 (signed)
1236 InstructionFoldingCase<uint64_t>(
1237 Header() + "%main = OpFunction %void None %void_func\n" +
1238 "%main_lab = OpLabel\n" +
1239 "%n = OpVariable %_ptr_int Function\n" +
1240 "%load = OpLoad %int %n\n" +
1241 "%2 = OpSMod %long %long_n7 %long_3\n" + "OpReturn\n" +
1242 "OpFunctionEnd",
1243 2, 2ll),
1244 // Test case 12: fold -7 rem 3 (signed)
1245 InstructionFoldingCase<uint64_t>(
1246 Header() + "%main = OpFunction %void None %void_func\n" +
1247 "%main_lab = OpLabel\n" +
1248 "%n = OpVariable %_ptr_int Function\n" +
1249 "%load = OpLoad %int %n\n" +
1250 "%2 = OpSRem %long %long_n7 %long_3\n" + "OpReturn\n" +
1251 "OpFunctionEnd",
1252 2, -1ll),
1253 // Test case 13: fold long(-24)
1254 InstructionFoldingCase<uint64_t>(
1255 Header() + "%main = OpFunction %void None %void_func\n" +
1256 "%main_lab = OpLabel\n" +
1257 "%n = OpVariable %_ptr_int Function\n" +
1258 "%load = OpLoad %int %n\n" +
1259 "%2 = OpSConvert %long %int_n24\n" + "OpReturn\n" +
1260 "OpFunctionEnd",
1261 2, -24ll),
1262 // Test case 14: fold long(-24)
1263 InstructionFoldingCase<uint64_t>(
1264 Header() + "%main = OpFunction %void None %void_func\n" +
1265 "%main_lab = OpLabel\n" +
1266 "%n = OpVariable %_ptr_int Function\n" +
1267 "%load = OpLoad %int %n\n" + "%2 = OpSConvert %long %int_10\n" +
1268 "OpReturn\n" + "OpFunctionEnd",
1269 2, 10ll),
1270 // Test case 15: fold long(-24(short)).
1271 // The upper bits should be cleared. So 0xFFFFFFE8 should become
1272 // 0x000000000000FFE8.
1273 InstructionFoldingCase<uint64_t>(
1274 Header() + "%main = OpFunction %void None %void_func\n" +
1275 "%main_lab = OpLabel\n" + "%2 = OpUConvert %ulong %short_n5\n" +
1276 "OpReturn\n" + "OpFunctionEnd",
1277 2, 65531ull)));
1278
1279 using UIntVectorInstructionFoldingTest =
1280 ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint32_t>>>;
1281
TEST_P(UIntVectorInstructionFoldingTest,Case)1282 TEST_P(UIntVectorInstructionFoldingTest, Case) {
1283 const auto& tc = GetParam();
1284
1285 std::unique_ptr<IRContext> context;
1286 Instruction* inst;
1287 std::tie(context, inst) =
1288 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1289 CheckForExpectedVectorConstant(
1290 inst, tc.expected_result,
1291 [](const analysis::Constant* c) { return c->GetU32(); });
1292 }
1293
1294 // clang-format off
1295 INSTANTIATE_TEST_SUITE_P(TestCase, UIntVectorInstructionFoldingTest,
1296 ::testing::Values(
1297 // Test case 0: fold 0*n
1298 InstructionFoldingCase<std::vector<uint32_t>>(
1299 Header() + "%main = OpFunction %void None %void_func\n" +
1300 "%main_lab = OpLabel\n" +
1301 "%n = OpVariable %_ptr_int Function\n" +
1302 "%load = OpLoad %int %n\n" +
1303 "%2 = OpVectorShuffle %v2int %v2int_2_2 %v2int_2_3 0 3\n" +
1304 "OpReturn\n" +
1305 "OpFunctionEnd",
1306 2, {2,3}),
1307 InstructionFoldingCase<std::vector<uint32_t>>(
1308 Header() + "%main = OpFunction %void None %void_func\n" +
1309 "%main_lab = OpLabel\n" +
1310 "%n = OpVariable %_ptr_int Function\n" +
1311 "%load = OpLoad %int %n\n" +
1312 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" +
1313 "OpReturn\n" +
1314 "OpFunctionEnd",
1315 2, {0,3}),
1316 // Test case 4: fold bit-cast int -24 to unsigned int
1317 InstructionFoldingCase<std::vector<uint32_t>>(
1318 Header() + "%main = OpFunction %void None %void_func\n" +
1319 "%main_lab = OpLabel\n" +
1320 "%n = OpVariable %_ptr_int Function\n" +
1321 "%load = OpLoad %int %n\n" +
1322 "%2 = OpBitcast %v2uint %v2int_min_max\n" +
1323 "OpReturn\n" +
1324 "OpFunctionEnd",
1325 2, {2147483648, 2147483647}),
1326 // Test case 5: fold SNegate vector of uint
1327 InstructionFoldingCase<std::vector<uint32_t>>(
1328 Header() + "%main = OpFunction %void None %void_func\n" +
1329 "%main_lab = OpLabel\n" +
1330 "%n = OpVariable %_ptr_int Function\n" +
1331 "%load = OpLoad %int %n\n" +
1332 "%2 = OpSNegate %v2uint %v2uint_0x3f800000_0xbf800000\n" +
1333 "OpReturn\n" +
1334 "OpFunctionEnd",
1335 2, {static_cast<uint32_t>(-0x3f800000), static_cast<uint32_t>(-0xbf800000)}),
1336 // Test case 6: fold vector components of uint (including integer overflow)
1337 InstructionFoldingCase<std::vector<uint32_t>>(
1338 Header() + "%main = OpFunction %void None %void_func\n" +
1339 "%main_lab = OpLabel\n" +
1340 "%2 = OpIAdd %v2uint %v2uint_0x3f800000_0xbf800000 %v2uint_0x3f800000_0xbf800000\n" +
1341 "OpReturn\n" +
1342 "OpFunctionEnd",
1343 2, {0x7f000000u, 0x7f000000u}),
1344 // Test case 6: fold vector components of uint
1345 InstructionFoldingCase<std::vector<uint32_t>>(
1346 Header() + "%main = OpFunction %void None %void_func\n" +
1347 "%main_lab = OpLabel\n" +
1348 "%2 = OpSConvert %v2int %v2short_2_n5\n" +
1349 "OpReturn\n" +
1350 "OpFunctionEnd",
1351 2, {2,static_cast<uint32_t>(-5)}),
1352 // Test case 6: fold vector components of uint (incuding integer overflow)
1353 InstructionFoldingCase<std::vector<uint32_t>>(
1354 Header() + "%main = OpFunction %void None %void_func\n" +
1355 "%main_lab = OpLabel\n" +
1356 "%2 = OpUConvert %v2uint %v2short_2_n5\n" +
1357 "OpReturn\n" +
1358 "OpFunctionEnd",
1359 2, {2,65531})
1360 ));
1361 // clang-format on
1362
1363 using IntVectorInstructionFoldingTest =
1364 ::testing::TestWithParam<InstructionFoldingCase<std::vector<int32_t>>>;
1365
TEST_P(IntVectorInstructionFoldingTest,Case)1366 TEST_P(IntVectorInstructionFoldingTest, Case) {
1367 const auto& tc = GetParam();
1368
1369 std::unique_ptr<IRContext> context;
1370 Instruction* inst;
1371 std::tie(context, inst) =
1372 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1373
1374 CheckForExpectedVectorConstant(
1375 inst, tc.expected_result,
1376 [](const analysis::Constant* c) { return c->GetS32(); });
1377 }
1378
1379 // clang-format off
1380 INSTANTIATE_TEST_SUITE_P(TestCase, IntVectorInstructionFoldingTest,
1381 ::testing::Values(
1382 // Test case 0: fold negate of a vector
1383 InstructionFoldingCase<std::vector<int32_t>>(
1384 Header() + "%main = OpFunction %void None %void_func\n" +
1385 "%main_lab = OpLabel\n" +
1386 "%2 = OpSNegate %v2int %v2int_2_3\n" +
1387 "OpReturn\n" +
1388 "OpFunctionEnd",
1389 2, {-2, -3}),
1390 // Test case 1: fold negate of a vector containing negative values.
1391 InstructionFoldingCase<std::vector<int32_t>>(
1392 Header() + "%main = OpFunction %void None %void_func\n" +
1393 "%main_lab = OpLabel\n" +
1394 "%2 = OpSNegate %v2int %v2int_n1_n24\n" +
1395 "OpReturn\n" +
1396 "OpFunctionEnd",
1397 2, {1, 24}),
1398 // Test case 2: fold negate of a vector at the limits
1399 InstructionFoldingCase<std::vector<int32_t>>(
1400 Header() + "%main = OpFunction %void None %void_func\n" +
1401 "%main_lab = OpLabel\n" +
1402 "%2 = OpSNegate %v2int %v2int_min_max\n" +
1403 "OpReturn\n" +
1404 "OpFunctionEnd",
1405 2, {INT_MIN, -INT_MAX}),
1406 // Test case 3: fold vector components of int
1407 InstructionFoldingCase<std::vector<int32_t>>(
1408 Header() + "%main = OpFunction %void None %void_func\n" +
1409 "%main_lab = OpLabel\n" +
1410 "%2 = OpIMul %v2int %v2int_2_3 %v2int_2_3\n" +
1411 "OpReturn\n" +
1412 "OpFunctionEnd",
1413 2, {4,9})
1414 ));
1415 // clang-format on
1416
1417 using LongIntVectorInstructionFoldingTest =
1418 ::testing::TestWithParam<InstructionFoldingCase<std::vector<uint64_t>>>;
1419
TEST_P(LongIntVectorInstructionFoldingTest,Case)1420 TEST_P(LongIntVectorInstructionFoldingTest, Case) {
1421 const auto& tc = GetParam();
1422
1423 std::unique_ptr<IRContext> context;
1424 Instruction* inst;
1425 std::tie(context, inst) =
1426 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1427 CheckForExpectedVectorConstant(
1428 inst, tc.expected_result,
1429 [](const analysis::Constant* c) { return c->GetU64(); });
1430 }
1431
1432 // clang-format off
1433 INSTANTIATE_TEST_SUITE_P(TestCase, LongIntVectorInstructionFoldingTest,
1434 ::testing::Values(
1435 // Test case 0: fold {2,2} + {2,3} (Testing that the vector logic works
1436 // correctly. Scalar tests will check that the 64-bit values are correctly
1437 // folded.)
1438 InstructionFoldingCase<std::vector<uint64_t>>(
1439 Header() + "%main = OpFunction %void None %void_func\n" +
1440 "%main_lab = OpLabel\n" +
1441 "%n = OpVariable %_ptr_int Function\n" +
1442 "%load = OpLoad %int %n\n" +
1443 "%2 = OpIAdd %v2long %v2long_2_2 %v2long_2_3\n" +
1444 "OpReturn\n" +
1445 "OpFunctionEnd",
1446 2, {4,5}),
1447 // Test case 0: fold {2,2} / {2,3} (Testing that the vector logic works
1448 // correctly. Scalar tests will check that the 64-bit values are correctly
1449 // folded.)
1450 InstructionFoldingCase<std::vector<uint64_t>>(
1451 Header() + "%main = OpFunction %void None %void_func\n" +
1452 "%main_lab = OpLabel\n" +
1453 "%n = OpVariable %_ptr_int Function\n" +
1454 "%load = OpLoad %int %n\n" +
1455 "%2 = OpSDiv %v2long %v2long_2_2 %v2long_2_3\n" +
1456 "OpReturn\n" +
1457 "OpFunctionEnd",
1458 2, {1,0})
1459 ));
1460 // clang-format on
1461
1462 using DoubleVectorInstructionFoldingTest =
1463 ::testing::TestWithParam<InstructionFoldingCase<std::vector<double>>>;
1464
TEST_P(DoubleVectorInstructionFoldingTest,Case)1465 TEST_P(DoubleVectorInstructionFoldingTest, Case) {
1466 const auto& tc = GetParam();
1467
1468 std::unique_ptr<IRContext> context;
1469 Instruction* inst;
1470 std::tie(context, inst) =
1471 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1472 CheckForExpectedVectorConstant(
1473 inst, tc.expected_result,
1474 [](const analysis::Constant* c) { return c->GetDouble(); });
1475 }
1476
1477 // clang-format off
1478 INSTANTIATE_TEST_SUITE_P(TestCase, DoubleVectorInstructionFoldingTest,
1479 ::testing::Values(
1480 // Test case 0: bit-cast int {0x3FF00000,0x00000000,0xC05FD666,0x66666666}
1481 // to double vector
1482 InstructionFoldingCase<std::vector<double>>(
1483 Header() + "%main = OpFunction %void None %void_func\n" +
1484 "%main_lab = OpLabel\n" +
1485 "%2 = OpBitcast %v2double %v4int_0x3FF00000_0x00000000_0xC05FD666_0x66666666\n" +
1486 "OpReturn\n" +
1487 "OpFunctionEnd",
1488 2, {1.0,-127.35}),
1489 // Test case 1: OpVectorTimesMatrix Non-Zero Zero {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {1.0, 2.0, 3.0, 4.0} {0.0, 0.0, 0.0, 0.0}
1490 InstructionFoldingCase<std::vector<double>>(
1491 Header() +
1492 "%main = OpFunction %void None %void_func\n" +
1493 "%main_lab = OpLabel\n" +
1494 "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_null\n" +
1495 "OpReturn\n" +
1496 "OpFunctionEnd",
1497 2, {0.0,0.0,0.0,0.0}),
1498 // Test case 2: OpVectorTimesMatrix Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1499 InstructionFoldingCase<std::vector<double>>(
1500 Header() +
1501 "%main = OpFunction %void None %void_func\n" +
1502 "%main_lab = OpLabel\n" +
1503 "%2 = OpVectorTimesMatrix %v4double %v4double_null %mat4v4double_1_2_3_4\n" +
1504 "OpReturn\n" +
1505 "OpFunctionEnd",
1506 2, {0.0,0.0,0.0,0.0}),
1507 // Test case 3: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {1.0, 2.0, 3.0, 4.0} {30.0, 30.0, 30.0, 30.0}
1508 InstructionFoldingCase<std::vector<double>>(
1509 Header() +
1510 "%main = OpFunction %void None %void_func\n" +
1511 "%main_lab = OpLabel\n" +
1512 "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_1_2_3_4\n" +
1513 "OpReturn\n" +
1514 "OpFunctionEnd",
1515 2, {30.0,30.0,30.0,30.0}),
1516 // Test case 4: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {1.0, 2.0, 3.0, 4.0} {30.0, 0.0, 30.0, 0.0}
1517 InstructionFoldingCase<std::vector<double>>(
1518 Header() +
1519 "%main = OpFunction %void None %void_func\n" +
1520 "%main_lab = OpLabel\n" +
1521 "%2 = OpVectorTimesMatrix %v4double %v4double_1_2_3_4 %mat4v4double_1_2_3_4_null\n" +
1522 "OpReturn\n" +
1523 "OpFunctionEnd",
1524 2, {30.0,0.0,30.0,0.0}),
1525 // Test case 5: OpMatrixTimesVector Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {0.0, 0.0, 0.0, 0.0}
1526 InstructionFoldingCase<std::vector<double>>(
1527 Header() +
1528 "%main = OpFunction %void None %void_func\n" +
1529 "%main_lab = OpLabel\n" +
1530 "%2 = OpMatrixTimesVector %v4double %mat4v4double_null %v4double_1_2_3_4\n" +
1531 "OpReturn\n" +
1532 "OpFunctionEnd",
1533 2, {0.0,0.0,0.0,0.0}),
1534 // Test case 6: OpMatrixTimesVector Non-Zero Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1535 InstructionFoldingCase<std::vector<double>>(
1536 Header() +
1537 "%main = OpFunction %void None %void_func\n" +
1538 "%main_lab = OpLabel\n" +
1539 "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4 %v4double_null\n" +
1540 "OpReturn\n" +
1541 "OpFunctionEnd",
1542 2, {0.0,0.0,0.0,0.0}),
1543 // Test case 7: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {10.0, 20.0, 30.0, 40.0}
1544 InstructionFoldingCase<std::vector<double>>(
1545 Header() +
1546 "%main = OpFunction %void None %void_func\n" +
1547 "%main_lab = OpLabel\n" +
1548 "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4 %v4double_1_2_3_4\n" +
1549 "OpReturn\n" +
1550 "OpFunctionEnd",
1551 2, {10.0,20.0,30.0,40.0}),
1552 // Test case 8: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {10.0, 20.0, 30.0, 40.0}
1553 InstructionFoldingCase<std::vector<double>>(
1554 Header() +
1555 "%main = OpFunction %void None %void_func\n" +
1556 "%main_lab = OpLabel\n" +
1557 "%2 = OpMatrixTimesVector %v4double %mat4v4double_1_2_3_4_null %v4double_1_2_3_4\n" +
1558 "OpReturn\n" +
1559 "OpFunctionEnd",
1560 2, {4.0,8.0,12.0,16.0})
1561 ));
1562
1563 using FloatVectorInstructionFoldingTest =
1564 ::testing::TestWithParam<InstructionFoldingCase<std::vector<float>>>;
1565
TEST_P(FloatVectorInstructionFoldingTest,Case)1566 TEST_P(FloatVectorInstructionFoldingTest, Case) {
1567 const auto& tc = GetParam();
1568
1569 std::unique_ptr<IRContext> context;
1570 Instruction* inst;
1571 std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
1572 CheckForExpectedVectorConstant(inst, tc.expected_result, [](const analysis::Constant* c){ return c->GetFloat();});
1573 }
1574
1575 // clang-format off
1576 INSTANTIATE_TEST_SUITE_P(TestCase, FloatVectorInstructionFoldingTest,
1577 ::testing::Values(
1578 // Test case 0: FMix {2.0, 2.0}, {2.0, 3.0} {0.2,0.5}
1579 InstructionFoldingCase<std::vector<float>>(
1580 Header() + "%main = OpFunction %void None %void_func\n" +
1581 "%main_lab = OpLabel\n" +
1582 "%2 = OpExtInst %v2float %1 FMix %v2float_2_3 %v2float_0_0 %v2float_0p2_0p5\n" +
1583 "OpReturn\n" +
1584 "OpFunctionEnd",
1585 2, {1.6f,1.5f}),
1586 // Test case 1: bit-cast unsigned int vector {0x3f800000, 0xbf800000} to
1587 // float vector
1588 InstructionFoldingCase<std::vector<float>>(
1589 Header() + "%main = OpFunction %void None %void_func\n" +
1590 "%main_lab = OpLabel\n" +
1591 "%2 = OpBitcast %v2float %v2uint_0x3f800000_0xbf800000\n" +
1592 "OpReturn\n" +
1593 "OpFunctionEnd",
1594 2, {1.0f,-1.0f}),
1595 // Test case 2: bit-cast long int 0xbf8000003f800000 to float vector
1596 InstructionFoldingCase<std::vector<float>>(
1597 Header() + "%main = OpFunction %void None %void_func\n" +
1598 "%main_lab = OpLabel\n" +
1599 "%2 = OpBitcast %v2float %long_0xbf8000003f800000\n" +
1600 "OpReturn\n" +
1601 "OpFunctionEnd",
1602 2, {1.0f,-1.0f}),
1603 // Test case 3: OpVectorTimesMatrix Non-Zero Zero {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {1.0, 2.0, 3.0, 4.0} {0.0, 0.0, 0.0, 0.0}
1604 InstructionFoldingCase<std::vector<float>>(
1605 Header() +
1606 "%main = OpFunction %void None %void_func\n" +
1607 "%main_lab = OpLabel\n" +
1608 "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_null\n" +
1609 "OpReturn\n" +
1610 "OpFunctionEnd",
1611 2, {0.0f,0.0f,0.0f,0.0f}),
1612 // Test case 4: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {1.0, 2.0, 3.0, 4.0} {30.0, 0.0, 30.0, 0.0}
1613 InstructionFoldingCase<std::vector<float>>(
1614 Header() +
1615 "%main = OpFunction %void None %void_func\n" +
1616 "%main_lab = OpLabel\n" +
1617 "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_1_2_3_4_null\n" +
1618 "OpReturn\n" +
1619 "OpFunctionEnd",
1620 2, {30.0,0.0,30.0,0.0}),
1621 // Test case 5: OpVectorTimesMatrix Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1622 InstructionFoldingCase<std::vector<float>>(
1623 Header() +
1624 "%main = OpFunction %void None %void_func\n" +
1625 "%main_lab = OpLabel\n" +
1626 "%2 = OpVectorTimesMatrix %v4float %v4float_null %mat4v4float_1_2_3_4\n" +
1627 "OpReturn\n" +
1628 "OpFunctionEnd",
1629 2, {0.0f,0.0f,0.0f,0.0f}),
1630 // Test case 6: OpVectorTimesMatrix Non-Zero Non-Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {1.0, 2.0, 3.0, 4.0} {30.0, 30.0, 30.0, 30.0}
1631 InstructionFoldingCase<std::vector<float>>(
1632 Header() +
1633 "%main = OpFunction %void None %void_func\n" +
1634 "%main_lab = OpLabel\n" +
1635 "%2 = OpVectorTimesMatrix %v4float %v4float_1_2_3_4 %mat4v4float_1_2_3_4\n" +
1636 "OpReturn\n" +
1637 "OpFunctionEnd",
1638 2, {30.0f,30.0f,30.0f,30.0f}),
1639 // Test case 7: OpMatrixTimesVector Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0}} {0.0, 0.0, 0.0, 0.0}
1640 InstructionFoldingCase<std::vector<float>>(
1641 Header() +
1642 "%main = OpFunction %void None %void_func\n" +
1643 "%main_lab = OpLabel\n" +
1644 "%2 = OpMatrixTimesVector %v4float %mat4v4float_null %v4float_1_2_3_4\n" +
1645 "OpReturn\n" +
1646 "OpFunctionEnd",
1647 2, {0.0f,0.0f,0.0f,0.0f}),
1648 // Test case 8: OpMatrixTimesVector Non-Zero Zero {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {0.0, 0.0, 0.0, 0.0} {0.0, 0.0, 0.0, 0.0}
1649 InstructionFoldingCase<std::vector<float>>(
1650 Header() +
1651 "%main = OpFunction %void None %void_func\n" +
1652 "%main_lab = OpLabel\n" +
1653 "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4 %v4float_null\n" +
1654 "OpReturn\n" +
1655 "OpFunctionEnd",
1656 2, {0.0f,0.0f,0.0f,0.0f}),
1657 // Test case 9: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}, {1.0, 2.0, 3.0, 4.0}} {10.0, 20.0, 30.0, 40.0}
1658 InstructionFoldingCase<std::vector<float>>(
1659 Header() +
1660 "%main = OpFunction %void None %void_func\n" +
1661 "%main_lab = OpLabel\n" +
1662 "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4 %v4float_1_2_3_4\n" +
1663 "OpReturn\n" +
1664 "OpFunctionEnd",
1665 2, {10.0f,20.0f,30.0f,40.0f}),
1666 // Test case 10: OpMatrixTimesVector Non-Zero Non-Zero {1.0, 2.0, 3.0, 4.0} {{1.0, 2.0, 3.0, 4.0}, Null, {1.0, 2.0, 3.0, 4.0}, Null} {10.0, 20.0, 30.0, 40.0}
1667 InstructionFoldingCase<std::vector<float>>(
1668 Header() +
1669 "%main = OpFunction %void None %void_func\n" +
1670 "%main_lab = OpLabel\n" +
1671 "%2 = OpMatrixTimesVector %v4float %mat4v4float_1_2_3_4_null %v4float_1_2_3_4\n" +
1672 "OpReturn\n" +
1673 "OpFunctionEnd",
1674 2, {4.0,8.0,12.0,16.0})
1675 ));
1676 // clang-format on
1677
1678 using FloatMatrixInstructionFoldingTest = ::testing::TestWithParam<
1679 InstructionFoldingCase<std::vector<std::vector<float>>>>;
1680
TEST_P(FloatMatrixInstructionFoldingTest,Case)1681 TEST_P(FloatMatrixInstructionFoldingTest, Case) {
1682 const auto& tc = GetParam();
1683
1684 std::unique_ptr<IRContext> context;
1685 Instruction* inst;
1686 std::tie(context, inst) =
1687 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1688
1689 EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
1690 if (inst->opcode() == spv::Op::OpCopyObject) {
1691 analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
1692 inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
1693 analysis::ConstantManager* const_mgr = context->get_constant_mgr();
1694 const analysis::Constant* result = const_mgr->GetConstantFromInst(inst);
1695 EXPECT_NE(result, nullptr);
1696 if (result != nullptr) {
1697 std::vector<const analysis::Constant*> matrix =
1698 result->AsMatrixConstant()->GetComponents();
1699 EXPECT_EQ(matrix.size(), tc.expected_result.size());
1700 for (size_t c = 0; c < matrix.size(); c++) {
1701 if (matrix[c]->AsNullConstant() != nullptr) {
1702 matrix[c] = const_mgr->GetNullCompositeConstant(matrix[c]->type());
1703 }
1704 const analysis::VectorConstant* column_const =
1705 matrix[c]->AsVectorConstant();
1706 ASSERT_NE(column_const, nullptr);
1707 const std::vector<const analysis::Constant*>& column =
1708 column_const->GetComponents();
1709 EXPECT_EQ(column.size(), tc.expected_result[c].size());
1710 for (size_t r = 0; r < column.size(); r++) {
1711 EXPECT_EQ(tc.expected_result[c][r], column[r]->GetFloat());
1712 }
1713 }
1714 }
1715 }
1716 }
1717
1718 // clang-format off
1719 INSTANTIATE_TEST_SUITE_P(TestCase, FloatMatrixInstructionFoldingTest,
1720 ::testing::Values(
1721 // Test case 0: OpTranspose square null matrix
1722 InstructionFoldingCase<std::vector<std::vector<float>>>(
1723 Header() + "%main = OpFunction %void None %void_func\n" +
1724 "%main_lab = OpLabel\n" +
1725 "%2 = OpTranspose %mat4v4float %mat4v4float_null\n" +
1726 "OpReturn\n" +
1727 "OpFunctionEnd",
1728 2, {{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f, 0.0f}}),
1729 // Test case 1: OpTranspose rectangular null matrix
1730 InstructionFoldingCase<std::vector<std::vector<float>>>(
1731 Header() + "%main = OpFunction %void None %void_func\n" +
1732 "%main_lab = OpLabel\n" +
1733 "%2 = OpTranspose %mat4v2float %mat2v4float_null\n" +
1734 "OpReturn\n" +
1735 "OpFunctionEnd",
1736 2, {{0.0f, 0.0f},{0.0f, 0.0f},{0.0f, 0.0f},{0.0f, 0.0f}}),
1737 InstructionFoldingCase<std::vector<std::vector<float>>>(
1738 Header() + "%main = OpFunction %void None %void_func\n" +
1739 "%main_lab = OpLabel\n" +
1740 "%2 = OpTranspose %mat4v4float %mat4v4float_1_2_3_4\n" +
1741 "OpReturn\n" +
1742 "OpFunctionEnd",
1743 2, {{1.0f, 1.0f, 1.0f, 1.0f},{2.0f, 2.0f, 2.0f, 2.0f},{3.0f, 3.0f, 3.0f, 3.0f},{4.0f, 4.0f, 4.0f, 4.0f}})
1744 ));
1745 // clang-format on
1746
1747 using BooleanInstructionFoldingTest =
1748 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
1749
TEST_P(BooleanInstructionFoldingTest,Case)1750 TEST_P(BooleanInstructionFoldingTest, Case) {
1751 const auto& tc = GetParam();
1752
1753 std::unique_ptr<IRContext> context;
1754 Instruction* inst;
1755 std::tie(context, inst) =
1756 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
1757 CheckForExpectedScalarConstant(
1758 inst, tc.expected_result,
1759 [](const analysis::Constant* c) { return c->AsBoolConstant()->value(); });
1760 }
1761
1762 // clang-format off
1763 INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTest,
1764 ::testing::Values(
1765 // Test case 0: fold true || n
1766 InstructionFoldingCase<bool>(
1767 Header() + "%main = OpFunction %void None %void_func\n" +
1768 "%main_lab = OpLabel\n" +
1769 "%n = OpVariable %_ptr_bool Function\n" +
1770 "%load = OpLoad %bool %n\n" +
1771 "%2 = OpLogicalOr %bool %true %load\n" +
1772 "OpReturn\n" +
1773 "OpFunctionEnd",
1774 2, true),
1775 // Test case 1: fold n || true
1776 InstructionFoldingCase<bool>(
1777 Header() + "%main = OpFunction %void None %void_func\n" +
1778 "%main_lab = OpLabel\n" +
1779 "%n = OpVariable %_ptr_bool Function\n" +
1780 "%load = OpLoad %bool %n\n" +
1781 "%2 = OpLogicalOr %bool %load %true\n" +
1782 "OpReturn\n" +
1783 "OpFunctionEnd",
1784 2, true),
1785 // Test case 2: fold false && n
1786 InstructionFoldingCase<bool>(
1787 Header() + "%main = OpFunction %void None %void_func\n" +
1788 "%main_lab = OpLabel\n" +
1789 "%n = OpVariable %_ptr_bool Function\n" +
1790 "%load = OpLoad %bool %n\n" +
1791 "%2 = OpLogicalAnd %bool %false %load\n" +
1792 "OpReturn\n" +
1793 "OpFunctionEnd",
1794 2, false),
1795 // Test case 3: fold n && false
1796 InstructionFoldingCase<bool>(
1797 Header() + "%main = OpFunction %void None %void_func\n" +
1798 "%main_lab = OpLabel\n" +
1799 "%n = OpVariable %_ptr_bool Function\n" +
1800 "%load = OpLoad %bool %n\n" +
1801 "%2 = OpLogicalAnd %bool %load %false\n" +
1802 "OpReturn\n" +
1803 "OpFunctionEnd",
1804 2, false),
1805 // Test case 4: fold n < 0 (unsigned)
1806 InstructionFoldingCase<bool>(
1807 Header() + "%main = OpFunction %void None %void_func\n" +
1808 "%main_lab = OpLabel\n" +
1809 "%n = OpVariable %_ptr_uint Function\n" +
1810 "%load = OpLoad %uint %n\n" +
1811 "%2 = OpULessThan %bool %load %uint_0\n" +
1812 "OpReturn\n" +
1813 "OpFunctionEnd",
1814 2, false),
1815 // Test case 5: fold UINT_MAX < n (unsigned)
1816 InstructionFoldingCase<bool>(
1817 Header() + "%main = OpFunction %void None %void_func\n" +
1818 "%main_lab = OpLabel\n" +
1819 "%n = OpVariable %_ptr_uint Function\n" +
1820 "%load = OpLoad %uint %n\n" +
1821 "%2 = OpULessThan %bool %uint_max %load\n" +
1822 "OpReturn\n" +
1823 "OpFunctionEnd",
1824 2, false),
1825 // Test case 6: fold INT_MAX < n (signed)
1826 InstructionFoldingCase<bool>(
1827 Header() + "%main = OpFunction %void None %void_func\n" +
1828 "%main_lab = OpLabel\n" +
1829 "%n = OpVariable %_ptr_int Function\n" +
1830 "%load = OpLoad %int %n\n" +
1831 "%2 = OpSLessThan %bool %int_max %load\n" +
1832 "OpReturn\n" +
1833 "OpFunctionEnd",
1834 2, false),
1835 // Test case 7: fold n < INT_MIN (signed)
1836 InstructionFoldingCase<bool>(
1837 Header() + "%main = OpFunction %void None %void_func\n" +
1838 "%main_lab = OpLabel\n" +
1839 "%n = OpVariable %_ptr_int Function\n" +
1840 "%load = OpLoad %int %n\n" +
1841 "%2 = OpSLessThan %bool %load %int_min\n" +
1842 "OpReturn\n" +
1843 "OpFunctionEnd",
1844 2, false),
1845 // Test case 8: fold 0 > n (unsigned)
1846 InstructionFoldingCase<bool>(
1847 Header() + "%main = OpFunction %void None %void_func\n" +
1848 "%main_lab = OpLabel\n" +
1849 "%n = OpVariable %_ptr_uint Function\n" +
1850 "%load = OpLoad %uint %n\n" +
1851 "%2 = OpUGreaterThan %bool %uint_0 %load\n" +
1852 "OpReturn\n" +
1853 "OpFunctionEnd",
1854 2, false),
1855 // Test case 9: fold n > UINT_MAX (unsigned)
1856 InstructionFoldingCase<bool>(
1857 Header() + "%main = OpFunction %void None %void_func\n" +
1858 "%main_lab = OpLabel\n" +
1859 "%n = OpVariable %_ptr_uint Function\n" +
1860 "%load = OpLoad %uint %n\n" +
1861 "%2 = OpUGreaterThan %bool %load %uint_max\n" +
1862 "OpReturn\n" +
1863 "OpFunctionEnd",
1864 2, false),
1865 // Test case 10: fold n > INT_MAX (signed)
1866 InstructionFoldingCase<bool>(
1867 Header() + "%main = OpFunction %void None %void_func\n" +
1868 "%main_lab = OpLabel\n" +
1869 "%n = OpVariable %_ptr_int Function\n" +
1870 "%load = OpLoad %int %n\n" +
1871 "%2 = OpSGreaterThan %bool %load %int_max\n" +
1872 "OpReturn\n" +
1873 "OpFunctionEnd",
1874 2, false),
1875 // Test case 11: fold INT_MIN > n (signed)
1876 InstructionFoldingCase<bool>(
1877 Header() + "%main = OpFunction %void None %void_func\n" +
1878 "%main_lab = OpLabel\n" +
1879 "%n = OpVariable %_ptr_uint Function\n" +
1880 "%load = OpLoad %uint %n\n" +
1881 "%2 = OpSGreaterThan %bool %int_min %load\n" +
1882 "OpReturn\n" +
1883 "OpFunctionEnd",
1884 2, false),
1885 // Test case 12: fold 0 <= n (unsigned)
1886 InstructionFoldingCase<bool>(
1887 Header() + "%main = OpFunction %void None %void_func\n" +
1888 "%main_lab = OpLabel\n" +
1889 "%n = OpVariable %_ptr_uint Function\n" +
1890 "%load = OpLoad %uint %n\n" +
1891 "%2 = OpULessThanEqual %bool %uint_0 %load\n" +
1892 "OpReturn\n" +
1893 "OpFunctionEnd",
1894 2, true),
1895 // Test case 13: fold n <= UINT_MAX (unsigned)
1896 InstructionFoldingCase<bool>(
1897 Header() + "%main = OpFunction %void None %void_func\n" +
1898 "%main_lab = OpLabel\n" +
1899 "%n = OpVariable %_ptr_uint Function\n" +
1900 "%load = OpLoad %uint %n\n" +
1901 "%2 = OpULessThanEqual %bool %load %uint_max\n" +
1902 "OpReturn\n" +
1903 "OpFunctionEnd",
1904 2, true),
1905 // Test case 14: fold INT_MIN <= n (signed)
1906 InstructionFoldingCase<bool>(
1907 Header() + "%main = OpFunction %void None %void_func\n" +
1908 "%main_lab = OpLabel\n" +
1909 "%n = OpVariable %_ptr_int Function\n" +
1910 "%load = OpLoad %int %n\n" +
1911 "%2 = OpSLessThanEqual %bool %int_min %load\n" +
1912 "OpReturn\n" +
1913 "OpFunctionEnd",
1914 2, true),
1915 // Test case 15: fold n <= INT_MAX (signed)
1916 InstructionFoldingCase<bool>(
1917 Header() + "%main = OpFunction %void None %void_func\n" +
1918 "%main_lab = OpLabel\n" +
1919 "%n = OpVariable %_ptr_int Function\n" +
1920 "%load = OpLoad %int %n\n" +
1921 "%2 = OpSLessThanEqual %bool %load %int_max\n" +
1922 "OpReturn\n" +
1923 "OpFunctionEnd",
1924 2, true),
1925 // Test case 16: fold n >= 0 (unsigned)
1926 InstructionFoldingCase<bool>(
1927 Header() + "%main = OpFunction %void None %void_func\n" +
1928 "%main_lab = OpLabel\n" +
1929 "%n = OpVariable %_ptr_uint Function\n" +
1930 "%load = OpLoad %uint %n\n" +
1931 "%2 = OpUGreaterThanEqual %bool %load %uint_0\n" +
1932 "OpReturn\n" +
1933 "OpFunctionEnd",
1934 2, true),
1935 // Test case 17: fold UINT_MAX >= n (unsigned)
1936 InstructionFoldingCase<bool>(
1937 Header() + "%main = OpFunction %void None %void_func\n" +
1938 "%main_lab = OpLabel\n" +
1939 "%n = OpVariable %_ptr_uint Function\n" +
1940 "%load = OpLoad %uint %n\n" +
1941 "%2 = OpUGreaterThanEqual %bool %uint_max %load\n" +
1942 "OpReturn\n" +
1943 "OpFunctionEnd",
1944 2, true),
1945 // Test case 18: fold n >= INT_MIN (signed)
1946 InstructionFoldingCase<bool>(
1947 Header() + "%main = OpFunction %void None %void_func\n" +
1948 "%main_lab = OpLabel\n" +
1949 "%n = OpVariable %_ptr_int Function\n" +
1950 "%load = OpLoad %int %n\n" +
1951 "%2 = OpSGreaterThanEqual %bool %load %int_min\n" +
1952 "OpReturn\n" +
1953 "OpFunctionEnd",
1954 2, true),
1955 // Test case 19: fold INT_MAX >= n (signed)
1956 InstructionFoldingCase<bool>(
1957 Header() + "%main = OpFunction %void None %void_func\n" +
1958 "%main_lab = OpLabel\n" +
1959 "%n = OpVariable %_ptr_int Function\n" +
1960 "%load = OpLoad %int %n\n" +
1961 "%2 = OpSGreaterThanEqual %bool %int_max %load\n" +
1962 "OpReturn\n" +
1963 "OpFunctionEnd",
1964 2, true)
1965 ));
1966
1967 INSTANTIATE_TEST_SUITE_P(FClampAndCmpLHS, BooleanInstructionFoldingTest,
1968 ::testing::Values(
1969 // Test case 0: fold 0.0 > clamp(n, 0.0, 1.0)
1970 InstructionFoldingCase<bool>(
1971 Header() + "%main = OpFunction %void None %void_func\n" +
1972 "%main_lab = OpLabel\n" +
1973 "%n = OpVariable %_ptr_float Function\n" +
1974 "%ld = OpLoad %float %n\n" +
1975 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
1976 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
1977 "OpReturn\n" +
1978 "OpFunctionEnd",
1979 2, false),
1980 // Test case 1: fold 0.0 > clamp(n, -1.0, -1.0)
1981 InstructionFoldingCase<bool>(
1982 Header() + "%main = OpFunction %void None %void_func\n" +
1983 "%main_lab = OpLabel\n" +
1984 "%n = OpVariable %_ptr_float Function\n" +
1985 "%ld = OpLoad %float %n\n" +
1986 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
1987 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
1988 "OpReturn\n" +
1989 "OpFunctionEnd",
1990 2, true),
1991 // Test case 2: fold 0.0 >= clamp(n, 1, 2)
1992 InstructionFoldingCase<bool>(
1993 Header() + "%main = OpFunction %void None %void_func\n" +
1994 "%main_lab = OpLabel\n" +
1995 "%n = OpVariable %_ptr_float Function\n" +
1996 "%ld = OpLoad %float %n\n" +
1997 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
1998 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
1999 "OpReturn\n" +
2000 "OpFunctionEnd",
2001 2, false),
2002 // Test case 3: fold 0.0 >= clamp(n, -1.0, 0.0)
2003 InstructionFoldingCase<bool>(
2004 Header() + "%main = OpFunction %void None %void_func\n" +
2005 "%main_lab = OpLabel\n" +
2006 "%n = OpVariable %_ptr_float Function\n" +
2007 "%ld = OpLoad %float %n\n" +
2008 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2009 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
2010 "OpReturn\n" +
2011 "OpFunctionEnd",
2012 2, true),
2013 // Test case 4: fold 0.0 <= clamp(n, 0.0, 1.0)
2014 InstructionFoldingCase<bool>(
2015 Header() + "%main = OpFunction %void None %void_func\n" +
2016 "%main_lab = OpLabel\n" +
2017 "%n = OpVariable %_ptr_float Function\n" +
2018 "%ld = OpLoad %float %n\n" +
2019 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2020 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
2021 "OpReturn\n" +
2022 "OpFunctionEnd",
2023 2, true),
2024 // Test case 5: fold 0.0 <= clamp(n, -1.0, -1.0)
2025 InstructionFoldingCase<bool>(
2026 Header() + "%main = OpFunction %void None %void_func\n" +
2027 "%main_lab = OpLabel\n" +
2028 "%n = OpVariable %_ptr_float Function\n" +
2029 "%ld = OpLoad %float %n\n" +
2030 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
2031 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
2032 "OpReturn\n" +
2033 "OpFunctionEnd",
2034 2, false),
2035 // Test case 6: fold 0.0 < clamp(n, 1, 2)
2036 InstructionFoldingCase<bool>(
2037 Header() + "%main = OpFunction %void None %void_func\n" +
2038 "%main_lab = OpLabel\n" +
2039 "%n = OpVariable %_ptr_float Function\n" +
2040 "%ld = OpLoad %float %n\n" +
2041 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2042 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
2043 "OpReturn\n" +
2044 "OpFunctionEnd",
2045 2, true),
2046 // Test case 7: fold 0.0 < clamp(n, -1.0, 0.0)
2047 InstructionFoldingCase<bool>(
2048 Header() + "%main = OpFunction %void None %void_func\n" +
2049 "%main_lab = OpLabel\n" +
2050 "%n = OpVariable %_ptr_float Function\n" +
2051 "%ld = OpLoad %float %n\n" +
2052 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2053 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
2054 "OpReturn\n" +
2055 "OpFunctionEnd",
2056 2, false),
2057 // Test case 8: fold 0.0 > clamp(n, 0.0, 1.0)
2058 InstructionFoldingCase<bool>(
2059 Header() + "%main = OpFunction %void None %void_func\n" +
2060 "%main_lab = OpLabel\n" +
2061 "%n = OpVariable %_ptr_float Function\n" +
2062 "%ld = OpLoad %float %n\n" +
2063 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2064 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
2065 "OpReturn\n" +
2066 "OpFunctionEnd",
2067 2, false),
2068 // Test case 9: fold 0.0 > clamp(n, -1.0, -1.0)
2069 InstructionFoldingCase<bool>(
2070 Header() + "%main = OpFunction %void None %void_func\n" +
2071 "%main_lab = OpLabel\n" +
2072 "%n = OpVariable %_ptr_float Function\n" +
2073 "%ld = OpLoad %float %n\n" +
2074 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
2075 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
2076 "OpReturn\n" +
2077 "OpFunctionEnd",
2078 2, true),
2079 // Test case 10: fold 0.0 >= clamp(n, 1, 2)
2080 InstructionFoldingCase<bool>(
2081 Header() + "%main = OpFunction %void None %void_func\n" +
2082 "%main_lab = OpLabel\n" +
2083 "%n = OpVariable %_ptr_float Function\n" +
2084 "%ld = OpLoad %float %n\n" +
2085 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2086 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
2087 "OpReturn\n" +
2088 "OpFunctionEnd",
2089 2, false),
2090 // Test case 11: fold 0.0 >= clamp(n, -1.0, 0.0)
2091 InstructionFoldingCase<bool>(
2092 Header() + "%main = OpFunction %void None %void_func\n" +
2093 "%main_lab = OpLabel\n" +
2094 "%n = OpVariable %_ptr_float Function\n" +
2095 "%ld = OpLoad %float %n\n" +
2096 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2097 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
2098 "OpReturn\n" +
2099 "OpFunctionEnd",
2100 2, true),
2101 // Test case 12: fold 0.0 <= clamp(n, 0.0, 1.0)
2102 InstructionFoldingCase<bool>(
2103 Header() + "%main = OpFunction %void None %void_func\n" +
2104 "%main_lab = OpLabel\n" +
2105 "%n = OpVariable %_ptr_float Function\n" +
2106 "%ld = OpLoad %float %n\n" +
2107 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2108 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
2109 "OpReturn\n" +
2110 "OpFunctionEnd",
2111 2, true),
2112 // Test case 13: fold 0.0 <= clamp(n, -1.0, -1.0)
2113 InstructionFoldingCase<bool>(
2114 Header() + "%main = OpFunction %void None %void_func\n" +
2115 "%main_lab = OpLabel\n" +
2116 "%n = OpVariable %_ptr_float Function\n" +
2117 "%ld = OpLoad %float %n\n" +
2118 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" +
2119 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
2120 "OpReturn\n" +
2121 "OpFunctionEnd",
2122 2, false),
2123 // Test case 14: fold 0.0 < clamp(n, 1, 2)
2124 InstructionFoldingCase<bool>(
2125 Header() + "%main = OpFunction %void None %void_func\n" +
2126 "%main_lab = OpLabel\n" +
2127 "%n = OpVariable %_ptr_float Function\n" +
2128 "%ld = OpLoad %float %n\n" +
2129 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2130 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
2131 "OpReturn\n" +
2132 "OpFunctionEnd",
2133 2, true),
2134 // Test case 15: fold 0.0 < clamp(n, -1.0, 0.0)
2135 InstructionFoldingCase<bool>(
2136 Header() + "%main = OpFunction %void None %void_func\n" +
2137 "%main_lab = OpLabel\n" +
2138 "%n = OpVariable %_ptr_float Function\n" +
2139 "%ld = OpLoad %float %n\n" +
2140 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2141 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
2142 "OpReturn\n" +
2143 "OpFunctionEnd",
2144 2, false)
2145 ));
2146
2147 INSTANTIATE_TEST_SUITE_P(FClampAndCmpRHS, BooleanInstructionFoldingTest,
2148 ::testing::Values(
2149 // Test case 0: fold clamp(n, 0.0, 1.0) > 1.0
2150 InstructionFoldingCase<bool>(
2151 Header() + "%main = OpFunction %void None %void_func\n" +
2152 "%main_lab = OpLabel\n" +
2153 "%n = OpVariable %_ptr_float Function\n" +
2154 "%ld = OpLoad %float %n\n" +
2155 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2156 "%2 = OpFOrdGreaterThan %bool %clamp %float_1\n" +
2157 "OpReturn\n" +
2158 "OpFunctionEnd",
2159 2, false),
2160 // Test case 1: fold clamp(n, 1.0, 1.0) > 0.0
2161 InstructionFoldingCase<bool>(
2162 Header() + "%main = OpFunction %void None %void_func\n" +
2163 "%main_lab = OpLabel\n" +
2164 "%n = OpVariable %_ptr_float Function\n" +
2165 "%ld = OpLoad %float %n\n" +
2166 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
2167 "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
2168 "OpReturn\n" +
2169 "OpFunctionEnd",
2170 2, true),
2171 // Test case 2: fold clamp(n, 1, 2) >= 0.0
2172 InstructionFoldingCase<bool>(
2173 Header() + "%main = OpFunction %void None %void_func\n" +
2174 "%main_lab = OpLabel\n" +
2175 "%n = OpVariable %_ptr_float Function\n" +
2176 "%ld = OpLoad %float %n\n" +
2177 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2178 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
2179 "OpReturn\n" +
2180 "OpFunctionEnd",
2181 2, true),
2182 // Test case 3: fold clamp(n, 1.0, 2.0) >= 3.0
2183 InstructionFoldingCase<bool>(
2184 Header() + "%main = OpFunction %void None %void_func\n" +
2185 "%main_lab = OpLabel\n" +
2186 "%n = OpVariable %_ptr_float Function\n" +
2187 "%ld = OpLoad %float %n\n" +
2188 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2189 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_3\n" +
2190 "OpReturn\n" +
2191 "OpFunctionEnd",
2192 2, false),
2193 // Test case 4: fold clamp(n, 0.0, 1.0) <= 1.0
2194 InstructionFoldingCase<bool>(
2195 Header() + "%main = OpFunction %void None %void_func\n" +
2196 "%main_lab = OpLabel\n" +
2197 "%n = OpVariable %_ptr_float Function\n" +
2198 "%ld = OpLoad %float %n\n" +
2199 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2200 "%2 = OpFOrdLessThanEqual %bool %clamp %float_1\n" +
2201 "OpReturn\n" +
2202 "OpFunctionEnd",
2203 2, true),
2204 // Test case 5: fold clamp(n, 1.0, 2.0) <= 0.0
2205 InstructionFoldingCase<bool>(
2206 Header() + "%main = OpFunction %void None %void_func\n" +
2207 "%main_lab = OpLabel\n" +
2208 "%n = OpVariable %_ptr_float Function\n" +
2209 "%ld = OpLoad %float %n\n" +
2210 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2211 "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
2212 "OpReturn\n" +
2213 "OpFunctionEnd",
2214 2, false),
2215 // Test case 6: fold clamp(n, 1, 2) < 3
2216 InstructionFoldingCase<bool>(
2217 Header() + "%main = OpFunction %void None %void_func\n" +
2218 "%main_lab = OpLabel\n" +
2219 "%n = OpVariable %_ptr_float Function\n" +
2220 "%ld = OpLoad %float %n\n" +
2221 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2222 "%2 = OpFOrdLessThan %bool %clamp %float_3\n" +
2223 "OpReturn\n" +
2224 "OpFunctionEnd",
2225 2, true),
2226 // Test case 7: fold clamp(n, -1.0, 0.0) < -1.0
2227 InstructionFoldingCase<bool>(
2228 Header() + "%main = OpFunction %void None %void_func\n" +
2229 "%main_lab = OpLabel\n" +
2230 "%n = OpVariable %_ptr_float Function\n" +
2231 "%ld = OpLoad %float %n\n" +
2232 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2233 "%2 = OpFOrdLessThan %bool %clamp %float_n1\n" +
2234 "OpReturn\n" +
2235 "OpFunctionEnd",
2236 2, false),
2237 // Test case 8: fold clamp(n, 0.0, 1.0) > 1.0
2238 InstructionFoldingCase<bool>(
2239 Header() + "%main = OpFunction %void None %void_func\n" +
2240 "%main_lab = OpLabel\n" +
2241 "%n = OpVariable %_ptr_float Function\n" +
2242 "%ld = OpLoad %float %n\n" +
2243 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2244 "%2 = OpFUnordGreaterThan %bool %clamp %float_1\n" +
2245 "OpReturn\n" +
2246 "OpFunctionEnd",
2247 2, false),
2248 // Test case 9: fold clamp(n, 1.0, 2.0) > 0.0
2249 InstructionFoldingCase<bool>(
2250 Header() + "%main = OpFunction %void None %void_func\n" +
2251 "%main_lab = OpLabel\n" +
2252 "%n = OpVariable %_ptr_float Function\n" +
2253 "%ld = OpLoad %float %n\n" +
2254 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2255 "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
2256 "OpReturn\n" +
2257 "OpFunctionEnd",
2258 2, true),
2259 // Test case 10: fold clamp(n, 1, 2) >= 3.0
2260 InstructionFoldingCase<bool>(
2261 Header() + "%main = OpFunction %void None %void_func\n" +
2262 "%main_lab = OpLabel\n" +
2263 "%n = OpVariable %_ptr_float Function\n" +
2264 "%ld = OpLoad %float %n\n" +
2265 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2266 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_3\n" +
2267 "OpReturn\n" +
2268 "OpFunctionEnd",
2269 2, false),
2270 // Test case 11: fold clamp(n, -1.0, 0.0) >= -1.0
2271 InstructionFoldingCase<bool>(
2272 Header() + "%main = OpFunction %void None %void_func\n" +
2273 "%main_lab = OpLabel\n" +
2274 "%n = OpVariable %_ptr_float Function\n" +
2275 "%ld = OpLoad %float %n\n" +
2276 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2277 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_n1\n" +
2278 "OpReturn\n" +
2279 "OpFunctionEnd",
2280 2, true),
2281 // Test case 12: fold clamp(n, 0.0, 1.0) <= 1.0
2282 InstructionFoldingCase<bool>(
2283 Header() + "%main = OpFunction %void None %void_func\n" +
2284 "%main_lab = OpLabel\n" +
2285 "%n = OpVariable %_ptr_float Function\n" +
2286 "%ld = OpLoad %float %n\n" +
2287 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
2288 "%2 = OpFUnordLessThanEqual %bool %clamp %float_1\n" +
2289 "OpReturn\n" +
2290 "OpFunctionEnd",
2291 2, true),
2292 // Test case 13: fold clamp(n, 1.0, 1.0) <= 0.0
2293 InstructionFoldingCase<bool>(
2294 Header() + "%main = OpFunction %void None %void_func\n" +
2295 "%main_lab = OpLabel\n" +
2296 "%n = OpVariable %_ptr_float Function\n" +
2297 "%ld = OpLoad %float %n\n" +
2298 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" +
2299 "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
2300 "OpReturn\n" +
2301 "OpFunctionEnd",
2302 2, false),
2303 // Test case 14: fold clamp(n, 1, 2) < 3
2304 InstructionFoldingCase<bool>(
2305 Header() + "%main = OpFunction %void None %void_func\n" +
2306 "%main_lab = OpLabel\n" +
2307 "%n = OpVariable %_ptr_float Function\n" +
2308 "%ld = OpLoad %float %n\n" +
2309 "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" +
2310 "%2 = OpFUnordLessThan %bool %clamp %float_3\n" +
2311 "OpReturn\n" +
2312 "OpFunctionEnd",
2313 2, true),
2314 // Test case 15: fold clamp(n, -1.0, 0.0) < -1.0
2315 InstructionFoldingCase<bool>(
2316 Header() + "%main = OpFunction %void None %void_func\n" +
2317 "%main_lab = OpLabel\n" +
2318 "%n = OpVariable %_ptr_float Function\n" +
2319 "%ld = OpLoad %float %n\n" +
2320 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
2321 "%2 = OpFUnordLessThan %bool %clamp %float_n1\n" +
2322 "OpReturn\n" +
2323 "OpFunctionEnd",
2324 2, false),
2325 // Test case 16: fold clamp(n, -1.0, 0.0) < -1.0 (one test for double)
2326 InstructionFoldingCase<bool>(
2327 Header() + "%main = OpFunction %void None %void_func\n" +
2328 "%main_lab = OpLabel\n" +
2329 "%n = OpVariable %_ptr_double Function\n" +
2330 "%ld = OpLoad %double %n\n" +
2331 "%clamp = OpExtInst %double %1 FClamp %ld %double_n1 %double_0\n" +
2332 "%2 = OpFUnordLessThan %bool %clamp %double_n1\n" +
2333 "OpReturn\n" +
2334 "OpFunctionEnd",
2335 2, false)
2336 ));
2337 // clang-format on
2338
2339 using FloatInstructionFoldingTest =
2340 ::testing::TestWithParam<InstructionFoldingCase<float>>;
2341
TEST_P(FloatInstructionFoldingTest,Case)2342 TEST_P(FloatInstructionFoldingTest, Case) {
2343 const auto& tc = GetParam();
2344
2345 std::unique_ptr<IRContext> context;
2346 Instruction* inst;
2347 std::tie(context, inst) =
2348 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
2349
2350 CheckForExpectedScalarConstant(inst, tc.expected_result,
2351 [](const analysis::Constant* c) {
2352 return c->AsFloatConstant()->GetFloatValue();
2353 });
2354 }
2355
2356 // Not testing NaNs because there are no expectations concerning NaNs according
2357 // to the "Precision and Operation of SPIR-V Instructions" section of the Vulkan
2358 // specification.
2359
2360 // clang-format off
2361 INSTANTIATE_TEST_SUITE_P(FloatConstantFoldingTest, FloatInstructionFoldingTest,
2362 ::testing::Values(
2363 // Test case 0: Fold 2.0 - 1.0
2364 InstructionFoldingCase<float>(
2365 Header() + "%main = OpFunction %void None %void_func\n" +
2366 "%main_lab = OpLabel\n" +
2367 "%2 = OpFSub %float %float_2 %float_1\n" +
2368 "OpReturn\n" +
2369 "OpFunctionEnd",
2370 2, 1.0),
2371 // Test case 1: Fold 2.0 + 1.0
2372 InstructionFoldingCase<float>(
2373 Header() + "%main = OpFunction %void None %void_func\n" +
2374 "%main_lab = OpLabel\n" +
2375 "%2 = OpFAdd %float %float_2 %float_1\n" +
2376 "OpReturn\n" +
2377 "OpFunctionEnd",
2378 2, 3.0),
2379 // Test case 2: Fold 3.0 * 2.0
2380 InstructionFoldingCase<float>(
2381 Header() + "%main = OpFunction %void None %void_func\n" +
2382 "%main_lab = OpLabel\n" +
2383 "%2 = OpFMul %float %float_3 %float_2\n" +
2384 "OpReturn\n" +
2385 "OpFunctionEnd",
2386 2, 6.0),
2387 // Test case 3: Fold 1.0 / 2.0
2388 InstructionFoldingCase<float>(
2389 Header() + "%main = OpFunction %void None %void_func\n" +
2390 "%main_lab = OpLabel\n" +
2391 "%2 = OpFDiv %float %float_1 %float_2\n" +
2392 "OpReturn\n" +
2393 "OpFunctionEnd",
2394 2, 0.5),
2395 // Test case 4: Fold 1.0 / 0.0
2396 InstructionFoldingCase<float>(
2397 Header() + "%main = OpFunction %void None %void_func\n" +
2398 "%main_lab = OpLabel\n" +
2399 "%2 = OpFDiv %float %float_1 %float_0\n" +
2400 "OpReturn\n" +
2401 "OpFunctionEnd",
2402 2, std::numeric_limits<float>::infinity()),
2403 // Test case 5: Fold -1.0 / 0.0
2404 InstructionFoldingCase<float>(
2405 Header() + "%main = OpFunction %void None %void_func\n" +
2406 "%main_lab = OpLabel\n" +
2407 "%2 = OpFDiv %float %float_n1 %float_0\n" +
2408 "OpReturn\n" +
2409 "OpFunctionEnd",
2410 2, -std::numeric_limits<float>::infinity()),
2411 // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
2412 InstructionFoldingCase<float>(
2413 Header() + "%main = OpFunction %void None %void_func\n" +
2414 "%main_lab = OpLabel\n" +
2415 "%2 = OpDot %float %v2float_2_3 %v2float_2_0p5\n" +
2416 "OpReturn\n" +
2417 "OpFunctionEnd",
2418 2, 5.5f),
2419 // Test case 7: Fold (0.0, 0.0) dot v
2420 InstructionFoldingCase<float>(
2421 Header() + "%main = OpFunction %void None %void_func\n" +
2422 "%main_lab = OpLabel\n" +
2423 "%v = OpVariable %_ptr_v2float Function\n" +
2424 "%2 = OpLoad %v2float %v\n" +
2425 "%3 = OpDot %float %v2float_0_0 %2\n" +
2426 "OpReturn\n" +
2427 "OpFunctionEnd",
2428 3, 0.0f),
2429 // Test case 8: Fold v dot (0.0, 0.0)
2430 InstructionFoldingCase<float>(
2431 Header() + "%main = OpFunction %void None %void_func\n" +
2432 "%main_lab = OpLabel\n" +
2433 "%v = OpVariable %_ptr_v2float Function\n" +
2434 "%2 = OpLoad %v2float %v\n" +
2435 "%3 = OpDot %float %2 %v2float_0_0\n" +
2436 "OpReturn\n" +
2437 "OpFunctionEnd",
2438 3, 0.0f),
2439 // Test case 9: Fold Null dot v
2440 InstructionFoldingCase<float>(
2441 Header() + "%main = OpFunction %void None %void_func\n" +
2442 "%main_lab = OpLabel\n" +
2443 "%v = OpVariable %_ptr_v2float Function\n" +
2444 "%2 = OpLoad %v2float %v\n" +
2445 "%3 = OpDot %float %v2float_null %2\n" +
2446 "OpReturn\n" +
2447 "OpFunctionEnd",
2448 3, 0.0f),
2449 // Test case 10: Fold v dot Null
2450 InstructionFoldingCase<float>(
2451 Header() + "%main = OpFunction %void None %void_func\n" +
2452 "%main_lab = OpLabel\n" +
2453 "%v = OpVariable %_ptr_v2float Function\n" +
2454 "%2 = OpLoad %v2float %v\n" +
2455 "%3 = OpDot %float %2 %v2float_null\n" +
2456 "OpReturn\n" +
2457 "OpFunctionEnd",
2458 3, 0.0f),
2459 // Test case 11: Fold -2.0
2460 InstructionFoldingCase<float>(
2461 Header() + "%main = OpFunction %void None %void_func\n" +
2462 "%main_lab = OpLabel\n" +
2463 "%2 = OpFNegate %float %float_2\n" +
2464 "OpReturn\n" +
2465 "OpFunctionEnd",
2466 2, -2),
2467 // Test case 12: QuantizeToF16 1.0
2468 InstructionFoldingCase<float>(
2469 Header() + "%main = OpFunction %void None %void_func\n" +
2470 "%main_lab = OpLabel\n" +
2471 "%2 = OpQuantizeToF16 %float %float_1\n" +
2472 "OpReturn\n" +
2473 "OpFunctionEnd",
2474 2, 1.0),
2475 // Test case 13: QuantizeToF16 positive non exact
2476 InstructionFoldingCase<float>(
2477 Header() + "%main = OpFunction %void None %void_func\n" +
2478 "%main_lab = OpLabel\n" +
2479 "%2 = OpQuantizeToF16 %float %float_2049\n" +
2480 "OpReturn\n" +
2481 "OpFunctionEnd",
2482 2, 2048),
2483 // Test case 14: QuantizeToF16 negative non exact
2484 InstructionFoldingCase<float>(
2485 Header() + "%main = OpFunction %void None %void_func\n" +
2486 "%main_lab = OpLabel\n" +
2487 "%2 = OpQuantizeToF16 %float %float_n2049\n" +
2488 "OpReturn\n" +
2489 "OpFunctionEnd",
2490 2, -2048),
2491 // Test case 15: QuantizeToF16 large positive
2492 InstructionFoldingCase<float>(
2493 Header() + "%main = OpFunction %void None %void_func\n" +
2494 "%main_lab = OpLabel\n" +
2495 "%2 = OpQuantizeToF16 %float %float_1e16\n" +
2496 "OpReturn\n" +
2497 "OpFunctionEnd",
2498 2, std::numeric_limits<float>::infinity()),
2499 // Test case 16: QuantizeToF16 large negative
2500 InstructionFoldingCase<float>(
2501 Header() + "%main = OpFunction %void None %void_func\n" +
2502 "%main_lab = OpLabel\n" +
2503 "%2 = OpQuantizeToF16 %float %float_n1e16\n" +
2504 "OpReturn\n" +
2505 "OpFunctionEnd",
2506 2, -std::numeric_limits<float>::infinity()),
2507 // Test case 17: QuantizeToF16 small positive
2508 InstructionFoldingCase<float>(
2509 Header() + "%main = OpFunction %void None %void_func\n" +
2510 "%main_lab = OpLabel\n" +
2511 "%2 = OpQuantizeToF16 %float %float_1en16\n" +
2512 "OpReturn\n" +
2513 "OpFunctionEnd",
2514 2, 0.0),
2515 // Test case 18: QuantizeToF16 small negative
2516 InstructionFoldingCase<float>(
2517 Header() + "%main = OpFunction %void None %void_func\n" +
2518 "%main_lab = OpLabel\n" +
2519 "%2 = OpQuantizeToF16 %float %float_n1en16\n" +
2520 "OpReturn\n" +
2521 "OpFunctionEnd",
2522 2, 0.0),
2523 // Test case 19: QuantizeToF16 nan
2524 InstructionFoldingCase<float>(
2525 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
2526 "%main_lab = OpLabel\n" +
2527 "%2 = OpQuantizeToF16 %float %float_nan\n" +
2528 "OpReturn\n" +
2529 "OpFunctionEnd",
2530 2, std::numeric_limits<float>::quiet_NaN()),
2531 // Test case 20: FMix 1.0 4.0 0.2
2532 InstructionFoldingCase<float>(
2533 Header() + "%main = OpFunction %void None %void_func\n" +
2534 "%main_lab = OpLabel\n" +
2535 "%2 = OpExtInst %float %1 FMix %float_1 %float_4 %float_0p2\n" +
2536 "OpReturn\n" +
2537 "OpFunctionEnd",
2538 2, 1.6f),
2539 // Test case 21: FMin 1.0 4.0
2540 InstructionFoldingCase<float>(
2541 Header() + "%main = OpFunction %void None %void_func\n" +
2542 "%main_lab = OpLabel\n" +
2543 "%2 = OpExtInst %float %1 FMin %float_1 %float_4\n" +
2544 "OpReturn\n" +
2545 "OpFunctionEnd",
2546 2, 1.0f),
2547 // Test case 22: FMin 4.0 0.2
2548 InstructionFoldingCase<float>(
2549 Header() + "%main = OpFunction %void None %void_func\n" +
2550 "%main_lab = OpLabel\n" +
2551 "%2 = OpExtInst %float %1 FMin %float_4 %float_0p2\n" +
2552 "OpReturn\n" +
2553 "OpFunctionEnd",
2554 2, 0.2f),
2555 // Test case 23: FMax 1.0 4.0
2556 InstructionFoldingCase<float>(
2557 Header() + "%main = OpFunction %void None %void_func\n" +
2558 "%main_lab = OpLabel\n" +
2559 "%2 = OpExtInst %float %1 FMax %float_1 %float_4\n" +
2560 "OpReturn\n" +
2561 "OpFunctionEnd",
2562 2, 4.0f),
2563 // Test case 24: FMax 1.0 0.2
2564 InstructionFoldingCase<float>(
2565 Header() + "%main = OpFunction %void None %void_func\n" +
2566 "%main_lab = OpLabel\n" +
2567 "%2 = OpExtInst %float %1 FMax %float_1 %float_0p2\n" +
2568 "OpReturn\n" +
2569 "OpFunctionEnd",
2570 2, 1.0f),
2571 // Test case 25: FClamp 1.0 0.2 4.0
2572 InstructionFoldingCase<float>(
2573 Header() + "%main = OpFunction %void None %void_func\n" +
2574 "%main_lab = OpLabel\n" +
2575 "%2 = OpExtInst %float %1 FClamp %float_1 %float_0p2 %float_4\n" +
2576 "OpReturn\n" +
2577 "OpFunctionEnd",
2578 2, 1.0f),
2579 // Test case 26: FClamp 0.2 2.0 4.0
2580 InstructionFoldingCase<float>(
2581 Header() + "%main = OpFunction %void None %void_func\n" +
2582 "%main_lab = OpLabel\n" +
2583 "%2 = OpExtInst %float %1 FClamp %float_0p2 %float_2 %float_4\n" +
2584 "OpReturn\n" +
2585 "OpFunctionEnd",
2586 2, 2.0f),
2587 // Test case 27: FClamp 2049.0 2.0 4.0
2588 InstructionFoldingCase<float>(
2589 Header() + "%main = OpFunction %void None %void_func\n" +
2590 "%main_lab = OpLabel\n" +
2591 "%2 = OpExtInst %float %1 FClamp %float_2049 %float_2 %float_4\n" +
2592 "OpReturn\n" +
2593 "OpFunctionEnd",
2594 2, 4.0f),
2595 // Test case 28: FClamp 1.0 2.0 x
2596 InstructionFoldingCase<float>(
2597 Header() + "%main = OpFunction %void None %void_func\n" +
2598 "%main_lab = OpLabel\n" +
2599 "%undef = OpUndef %float\n" +
2600 "%2 = OpExtInst %float %1 FClamp %float_1 %float_2 %undef\n" +
2601 "OpReturn\n" +
2602 "OpFunctionEnd",
2603 2, 2.0),
2604 // Test case 29: FClamp 1.0 x 0.5
2605 InstructionFoldingCase<float>(
2606 Header() + "%main = OpFunction %void None %void_func\n" +
2607 "%main_lab = OpLabel\n" +
2608 "%undef = OpUndef %float\n" +
2609 "%2 = OpExtInst %float %1 FClamp %float_1 %undef %float_0p5\n" +
2610 "OpReturn\n" +
2611 "OpFunctionEnd",
2612 2, 0.5),
2613 // Test case 30: Sin 0.0
2614 InstructionFoldingCase<float>(
2615 Header() + "%main = OpFunction %void None %void_func\n" +
2616 "%main_lab = OpLabel\n" +
2617 "%2 = OpExtInst %float %1 Sin %float_0\n" +
2618 "OpReturn\n" +
2619 "OpFunctionEnd",
2620 2, 0.0),
2621 // Test case 31: Cos 0.0
2622 InstructionFoldingCase<float>(
2623 Header() + "%main = OpFunction %void None %void_func\n" +
2624 "%main_lab = OpLabel\n" +
2625 "%2 = OpExtInst %float %1 Cos %float_0\n" +
2626 "OpReturn\n" +
2627 "OpFunctionEnd",
2628 2, 1.0),
2629 // Test case 32: Tan 0.0
2630 InstructionFoldingCase<float>(
2631 Header() + "%main = OpFunction %void None %void_func\n" +
2632 "%main_lab = OpLabel\n" +
2633 "%2 = OpExtInst %float %1 Tan %float_0\n" +
2634 "OpReturn\n" +
2635 "OpFunctionEnd",
2636 2, 0.0),
2637 // Test case 33: Asin 0.0
2638 InstructionFoldingCase<float>(
2639 Header() + "%main = OpFunction %void None %void_func\n" +
2640 "%main_lab = OpLabel\n" +
2641 "%2 = OpExtInst %float %1 Asin %float_0\n" +
2642 "OpReturn\n" +
2643 "OpFunctionEnd",
2644 2, 0.0),
2645 // Test case 34: Acos 1.0
2646 InstructionFoldingCase<float>(
2647 Header() + "%main = OpFunction %void None %void_func\n" +
2648 "%main_lab = OpLabel\n" +
2649 "%2 = OpExtInst %float %1 Acos %float_1\n" +
2650 "OpReturn\n" +
2651 "OpFunctionEnd",
2652 2, 0.0),
2653 // Test case 35: Atan 0.0
2654 InstructionFoldingCase<float>(
2655 Header() + "%main = OpFunction %void None %void_func\n" +
2656 "%main_lab = OpLabel\n" +
2657 "%2 = OpExtInst %float %1 Atan %float_0\n" +
2658 "OpReturn\n" +
2659 "OpFunctionEnd",
2660 2, 0.0),
2661 // Test case 36: Exp 0.0
2662 InstructionFoldingCase<float>(
2663 Header() + "%main = OpFunction %void None %void_func\n" +
2664 "%main_lab = OpLabel\n" +
2665 "%2 = OpExtInst %float %1 Exp %float_0\n" +
2666 "OpReturn\n" +
2667 "OpFunctionEnd",
2668 2, 1.0),
2669 // Test case 37: Log 1.0
2670 InstructionFoldingCase<float>(
2671 Header() + "%main = OpFunction %void None %void_func\n" +
2672 "%main_lab = OpLabel\n" +
2673 "%2 = OpExtInst %float %1 Log %float_1\n" +
2674 "OpReturn\n" +
2675 "OpFunctionEnd",
2676 2, 0.0),
2677 // Test case 38: Exp2 2.0
2678 InstructionFoldingCase<float>(
2679 Header() + "%main = OpFunction %void None %void_func\n" +
2680 "%main_lab = OpLabel\n" +
2681 "%2 = OpExtInst %float %1 Exp2 %float_2\n" +
2682 "OpReturn\n" +
2683 "OpFunctionEnd",
2684 2, 4.0),
2685 // Test case 39: Log2 4.0
2686 InstructionFoldingCase<float>(
2687 Header() + "%main = OpFunction %void None %void_func\n" +
2688 "%main_lab = OpLabel\n" +
2689 "%2 = OpExtInst %float %1 Log2 %float_4\n" +
2690 "OpReturn\n" +
2691 "OpFunctionEnd",
2692 2, 2.0),
2693 // Test case 40: Sqrt 4.0
2694 InstructionFoldingCase<float>(
2695 Header() + "%main = OpFunction %void None %void_func\n" +
2696 "%main_lab = OpLabel\n" +
2697 "%2 = OpExtInst %float %1 Sqrt %float_4\n" +
2698 "OpReturn\n" +
2699 "OpFunctionEnd",
2700 2, 2.0),
2701 // Test case 41: Atan2 0.0 1.0
2702 InstructionFoldingCase<float>(
2703 Header() + "%main = OpFunction %void None %void_func\n" +
2704 "%main_lab = OpLabel\n" +
2705 "%2 = OpExtInst %float %1 Atan2 %float_0 %float_1\n" +
2706 "OpReturn\n" +
2707 "OpFunctionEnd",
2708 2, 0.0),
2709 // Test case 42: Pow 2.0 3.0
2710 InstructionFoldingCase<float>(
2711 Header() + "%main = OpFunction %void None %void_func\n" +
2712 "%main_lab = OpLabel\n" +
2713 "%2 = OpExtInst %float %1 Pow %float_2 %float_3\n" +
2714 "OpReturn\n" +
2715 "OpFunctionEnd",
2716 2, 8.0),
2717 // Test case 43: Fold 1.0 / -0.0.
2718 InstructionFoldingCase<float>(
2719 Header() + "%main = OpFunction %void None %void_func\n" +
2720 "%main_lab = OpLabel\n" +
2721 "%2 = OpFDiv %float %float_1 %float_n0\n" +
2722 "OpReturn\n" +
2723 "OpFunctionEnd",
2724 2, -std::numeric_limits<float>::infinity()),
2725 // Test case 44: Fold -1.0 / -0.0
2726 InstructionFoldingCase<float>(
2727 Header() + "%main = OpFunction %void None %void_func\n" +
2728 "%main_lab = OpLabel\n" +
2729 "%2 = OpFDiv %float %float_n1 %float_n0\n" +
2730 "OpReturn\n" +
2731 "OpFunctionEnd",
2732 2, std::numeric_limits<float>::infinity()),
2733 // Test case 45: Fold 0.0 / 0.0
2734 InstructionFoldingCase<float>(
2735 Header() + "%main = OpFunction %void None %void_func\n" +
2736 "%main_lab = OpLabel\n" +
2737 "%2 = OpFDiv %float %float_0 %float_0\n" +
2738 "OpReturn\n" +
2739 "OpFunctionEnd",
2740 2, std::numeric_limits<float>::quiet_NaN()),
2741 // Test case 46: Fold 0.0 / -0.0
2742 InstructionFoldingCase<float>(
2743 Header() + "%main = OpFunction %void None %void_func\n" +
2744 "%main_lab = OpLabel\n" +
2745 "%2 = OpFDiv %float %float_0 %float_n0\n" +
2746 "OpReturn\n" +
2747 "OpFunctionEnd",
2748 2, std::numeric_limits<float>::quiet_NaN())
2749 ));
2750 // clang-format on
2751
2752 using DoubleInstructionFoldingTest =
2753 ::testing::TestWithParam<InstructionFoldingCase<double>>;
2754
TEST_P(DoubleInstructionFoldingTest,Case)2755 TEST_P(DoubleInstructionFoldingTest, Case) {
2756 const auto& tc = GetParam();
2757
2758 std::unique_ptr<IRContext> context;
2759 Instruction* inst;
2760 std::tie(context, inst) =
2761 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
2762 CheckForExpectedScalarConstant(
2763 inst, tc.expected_result, [](const analysis::Constant* c) {
2764 return c->AsFloatConstant()->GetDoubleValue();
2765 });
2766 }
2767
2768 // clang-format off
2769 INSTANTIATE_TEST_SUITE_P(DoubleConstantFoldingTest, DoubleInstructionFoldingTest,
2770 ::testing::Values(
2771 // Test case 0: Fold 2.0 - 1.0
2772 InstructionFoldingCase<double>(
2773 Header() + "%main = OpFunction %void None %void_func\n" +
2774 "%main_lab = OpLabel\n" +
2775 "%2 = OpFSub %double %double_2 %double_1\n" +
2776 "OpReturn\n" +
2777 "OpFunctionEnd",
2778 2, 1.0),
2779 // Test case 1: Fold 2.0 + 1.0
2780 InstructionFoldingCase<double>(
2781 Header() + "%main = OpFunction %void None %void_func\n" +
2782 "%main_lab = OpLabel\n" +
2783 "%2 = OpFAdd %double %double_2 %double_1\n" +
2784 "OpReturn\n" +
2785 "OpFunctionEnd",
2786 2, 3.0),
2787 // Test case 2: Fold 3.0 * 2.0
2788 InstructionFoldingCase<double>(
2789 Header() + "%main = OpFunction %void None %void_func\n" +
2790 "%main_lab = OpLabel\n" +
2791 "%2 = OpFMul %double %double_3 %double_2\n" +
2792 "OpReturn\n" +
2793 "OpFunctionEnd",
2794 2, 6.0),
2795 // Test case 3: Fold 1.0 / 2.0
2796 InstructionFoldingCase<double>(
2797 Header() + "%main = OpFunction %void None %void_func\n" +
2798 "%main_lab = OpLabel\n" +
2799 "%2 = OpFDiv %double %double_1 %double_2\n" +
2800 "OpReturn\n" +
2801 "OpFunctionEnd",
2802 2, 0.5),
2803 // Test case 4: Fold 1.0 / 0.0
2804 InstructionFoldingCase<double>(
2805 Header() + "%main = OpFunction %void None %void_func\n" +
2806 "%main_lab = OpLabel\n" +
2807 "%2 = OpFDiv %double %double_1 %double_0\n" +
2808 "OpReturn\n" +
2809 "OpFunctionEnd",
2810 2, std::numeric_limits<double>::infinity()),
2811 // Test case 5: Fold -1.0 / 0.0
2812 InstructionFoldingCase<double>(
2813 Header() + "%main = OpFunction %void None %void_func\n" +
2814 "%main_lab = OpLabel\n" +
2815 "%2 = OpFDiv %double %double_n1 %double_0\n" +
2816 "OpReturn\n" +
2817 "OpFunctionEnd",
2818 2, -std::numeric_limits<double>::infinity()),
2819 // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5)
2820 InstructionFoldingCase<double>(
2821 Header() + "%main = OpFunction %void None %void_func\n" +
2822 "%main_lab = OpLabel\n" +
2823 "%2 = OpDot %double %v2double_2_3 %v2double_2_0p5\n" +
2824 "OpReturn\n" +
2825 "OpFunctionEnd",
2826 2, 5.5f),
2827 // Test case 7: Fold (0.0, 0.0) dot v
2828 InstructionFoldingCase<double>(
2829 Header() + "%main = OpFunction %void None %void_func\n" +
2830 "%main_lab = OpLabel\n" +
2831 "%v = OpVariable %_ptr_v2double Function\n" +
2832 "%2 = OpLoad %v2double %v\n" +
2833 "%3 = OpDot %double %v2double_0_0 %2\n" +
2834 "OpReturn\n" +
2835 "OpFunctionEnd",
2836 3, 0.0f),
2837 // Test case 8: Fold v dot (0.0, 0.0)
2838 InstructionFoldingCase<double>(
2839 Header() + "%main = OpFunction %void None %void_func\n" +
2840 "%main_lab = OpLabel\n" +
2841 "%v = OpVariable %_ptr_v2double Function\n" +
2842 "%2 = OpLoad %v2double %v\n" +
2843 "%3 = OpDot %double %2 %v2double_0_0\n" +
2844 "OpReturn\n" +
2845 "OpFunctionEnd",
2846 3, 0.0f),
2847 // Test case 9: Fold Null dot v
2848 InstructionFoldingCase<double>(
2849 Header() + "%main = OpFunction %void None %void_func\n" +
2850 "%main_lab = OpLabel\n" +
2851 "%v = OpVariable %_ptr_v2double Function\n" +
2852 "%2 = OpLoad %v2double %v\n" +
2853 "%3 = OpDot %double %v2double_null %2\n" +
2854 "OpReturn\n" +
2855 "OpFunctionEnd",
2856 3, 0.0f),
2857 // Test case 10: Fold v dot Null
2858 InstructionFoldingCase<double>(
2859 Header() + "%main = OpFunction %void None %void_func\n" +
2860 "%main_lab = OpLabel\n" +
2861 "%v = OpVariable %_ptr_v2double Function\n" +
2862 "%2 = OpLoad %v2double %v\n" +
2863 "%3 = OpDot %double %2 %v2double_null\n" +
2864 "OpReturn\n" +
2865 "OpFunctionEnd",
2866 3, 0.0f),
2867 // Test case 11: Fold -2.0
2868 InstructionFoldingCase<double>(
2869 Header() + "%main = OpFunction %void None %void_func\n" +
2870 "%main_lab = OpLabel\n" +
2871 "%2 = OpFNegate %double %double_2\n" +
2872 "OpReturn\n" +
2873 "OpFunctionEnd",
2874 2, -2),
2875 // Test case 12: FMin 1.0 4.0
2876 InstructionFoldingCase<double>(
2877 Header() + "%main = OpFunction %void None %void_func\n" +
2878 "%main_lab = OpLabel\n" +
2879 "%2 = OpExtInst %double %1 FMin %double_1 %double_4\n" +
2880 "OpReturn\n" +
2881 "OpFunctionEnd",
2882 2, 1.0),
2883 // Test case 13: FMin 4.0 0.2
2884 InstructionFoldingCase<double>(
2885 Header() + "%main = OpFunction %void None %void_func\n" +
2886 "%main_lab = OpLabel\n" +
2887 "%2 = OpExtInst %double %1 FMin %double_4 %double_0p2\n" +
2888 "OpReturn\n" +
2889 "OpFunctionEnd",
2890 2, 0.2),
2891 // Test case 14: FMax 1.0 4.0
2892 InstructionFoldingCase<double>(
2893 Header() + "%main = OpFunction %void None %void_func\n" +
2894 "%main_lab = OpLabel\n" +
2895 "%2 = OpExtInst %double %1 FMax %double_1 %double_4\n" +
2896 "OpReturn\n" +
2897 "OpFunctionEnd",
2898 2, 4.0),
2899 // Test case 15: FMax 1.0 0.2
2900 InstructionFoldingCase<double>(
2901 Header() + "%main = OpFunction %void None %void_func\n" +
2902 "%main_lab = OpLabel\n" +
2903 "%2 = OpExtInst %double %1 FMax %double_1 %double_0p2\n" +
2904 "OpReturn\n" +
2905 "OpFunctionEnd",
2906 2, 1.0),
2907 // Test case 16: FClamp 1.0 0.2 4.0
2908 InstructionFoldingCase<double>(
2909 Header() + "%main = OpFunction %void None %void_func\n" +
2910 "%main_lab = OpLabel\n" +
2911 "%2 = OpExtInst %double %1 FClamp %double_1 %double_0p2 %double_4\n" +
2912 "OpReturn\n" +
2913 "OpFunctionEnd",
2914 2, 1.0),
2915 // Test case 17: FClamp 0.2 2.0 4.0
2916 InstructionFoldingCase<double>(
2917 Header() + "%main = OpFunction %void None %void_func\n" +
2918 "%main_lab = OpLabel\n" +
2919 "%2 = OpExtInst %double %1 FClamp %double_0p2 %double_2 %double_4\n" +
2920 "OpReturn\n" +
2921 "OpFunctionEnd",
2922 2, 2.0),
2923 // Test case 18: FClamp 5.0 2.0 4.0
2924 InstructionFoldingCase<double>(
2925 Header() + "%main = OpFunction %void None %void_func\n" +
2926 "%main_lab = OpLabel\n" +
2927 "%2 = OpExtInst %double %1 FClamp %double_5 %double_2 %double_4\n" +
2928 "OpReturn\n" +
2929 "OpFunctionEnd",
2930 2, 4.0),
2931 // Test case 19: FClamp 1.0 2.0 x
2932 InstructionFoldingCase<double>(
2933 Header() + "%main = OpFunction %void None %void_func\n" +
2934 "%main_lab = OpLabel\n" +
2935 "%undef = OpUndef %double\n" +
2936 "%2 = OpExtInst %double %1 FClamp %double_1 %double_2 %undef\n" +
2937 "OpReturn\n" +
2938 "OpFunctionEnd",
2939 2, 2.0),
2940 // Test case 20: FClamp 1.0 x 0.5
2941 InstructionFoldingCase<double>(
2942 Header() + "%main = OpFunction %void None %void_func\n" +
2943 "%main_lab = OpLabel\n" +
2944 "%undef = OpUndef %double\n" +
2945 "%2 = OpExtInst %double %1 FClamp %double_1 %undef %double_0p5\n" +
2946 "OpReturn\n" +
2947 "OpFunctionEnd",
2948 2, 0.5),
2949 // Test case 21: Sqrt 4.0
2950 InstructionFoldingCase<double>(
2951 Header() + "%main = OpFunction %void None %void_func\n" +
2952 "%main_lab = OpLabel\n" +
2953 "%undef = OpUndef %double\n" +
2954 "%2 = OpExtInst %double %1 Sqrt %double_4\n" +
2955 "OpReturn\n" +
2956 "OpFunctionEnd",
2957 2, 2.0),
2958 // Test case 22: Pow 2.0 3.0
2959 InstructionFoldingCase<double>(
2960 Header() + "%main = OpFunction %void None %void_func\n" +
2961 "%main_lab = OpLabel\n" +
2962 "%undef = OpUndef %double\n" +
2963 "%2 = OpExtInst %double %1 Pow %double_2 %double_3\n" +
2964 "OpReturn\n" +
2965 "OpFunctionEnd",
2966 2, 8.0),
2967 // Test case 23: Fold 1.0 / -0.0.
2968 InstructionFoldingCase<double>(
2969 Header() + "%main = OpFunction %void None %void_func\n" +
2970 "%main_lab = OpLabel\n" +
2971 "%2 = OpFDiv %double %double_1 %double_n0\n" +
2972 "OpReturn\n" +
2973 "OpFunctionEnd",
2974 2, -std::numeric_limits<double>::infinity()),
2975 // Test case 24: Fold -1.0 / -0.0
2976 InstructionFoldingCase<double>(
2977 Header() + "%main = OpFunction %void None %void_func\n" +
2978 "%main_lab = OpLabel\n" +
2979 "%2 = OpFDiv %double %double_n1 %double_n0\n" +
2980 "OpReturn\n" +
2981 "OpFunctionEnd",
2982 2, std::numeric_limits<double>::infinity()),
2983 // Test case 25: Fold 0.0 / 0.0
2984 InstructionFoldingCase<double>(
2985 Header() + "%main = OpFunction %void None %void_func\n" +
2986 "%main_lab = OpLabel\n" +
2987 "%2 = OpFDiv %double %double_0 %double_0\n" +
2988 "OpReturn\n" +
2989 "OpFunctionEnd",
2990 2, std::numeric_limits<double>::quiet_NaN()),
2991 // Test case 26: Fold 0.0 / -0.0
2992 InstructionFoldingCase<double>(
2993 Header() + "%main = OpFunction %void None %void_func\n" +
2994 "%main_lab = OpLabel\n" +
2995 "%2 = OpFDiv %double %double_0 %double_n0\n" +
2996 "OpReturn\n" +
2997 "OpFunctionEnd",
2998 2, std::numeric_limits<double>::quiet_NaN())
2999 ));
3000 // clang-format on
3001
3002 // clang-format off
3003 INSTANTIATE_TEST_SUITE_P(DoubleOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3004 ::testing::Values(
3005 // Test case 0: fold 1.0 == 2.0
3006 InstructionFoldingCase<bool>(
3007 Header() + "%main = OpFunction %void None %void_func\n" +
3008 "%main_lab = OpLabel\n" +
3009 "%2 = OpFOrdEqual %bool %double_1 %double_2\n" +
3010 "OpReturn\n" +
3011 "OpFunctionEnd",
3012 2, false),
3013 // Test case 1: fold 1.0 != 2.0
3014 InstructionFoldingCase<bool>(
3015 Header() + "%main = OpFunction %void None %void_func\n" +
3016 "%main_lab = OpLabel\n" +
3017 "%2 = OpFOrdNotEqual %bool %double_1 %double_2\n" +
3018 "OpReturn\n" +
3019 "OpFunctionEnd",
3020 2, true),
3021 // Test case 2: fold 1.0 < 2.0
3022 InstructionFoldingCase<bool>(
3023 Header() + "%main = OpFunction %void None %void_func\n" +
3024 "%main_lab = OpLabel\n" +
3025 "%2 = OpFOrdLessThan %bool %double_1 %double_2\n" +
3026 "OpReturn\n" +
3027 "OpFunctionEnd",
3028 2, true),
3029 // Test case 3: fold 1.0 > 2.0
3030 InstructionFoldingCase<bool>(
3031 Header() + "%main = OpFunction %void None %void_func\n" +
3032 "%main_lab = OpLabel\n" +
3033 "%2 = OpFOrdGreaterThan %bool %double_1 %double_2\n" +
3034 "OpReturn\n" +
3035 "OpFunctionEnd",
3036 2, false),
3037 // Test case 4: fold 1.0 <= 2.0
3038 InstructionFoldingCase<bool>(
3039 Header() + "%main = OpFunction %void None %void_func\n" +
3040 "%main_lab = OpLabel\n" +
3041 "%2 = OpFOrdLessThanEqual %bool %double_1 %double_2\n" +
3042 "OpReturn\n" +
3043 "OpFunctionEnd",
3044 2, true),
3045 // Test case 5: fold 1.0 >= 2.0
3046 InstructionFoldingCase<bool>(
3047 Header() + "%main = OpFunction %void None %void_func\n" +
3048 "%main_lab = OpLabel\n" +
3049 "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_2\n" +
3050 "OpReturn\n" +
3051 "OpFunctionEnd",
3052 2, false),
3053 // Test case 6: fold 1.0 == 1.0
3054 InstructionFoldingCase<bool>(
3055 Header() + "%main = OpFunction %void None %void_func\n" +
3056 "%main_lab = OpLabel\n" +
3057 "%2 = OpFOrdEqual %bool %double_1 %double_1\n" +
3058 "OpReturn\n" +
3059 "OpFunctionEnd",
3060 2, true),
3061 // Test case 7: fold 1.0 != 1.0
3062 InstructionFoldingCase<bool>(
3063 Header() + "%main = OpFunction %void None %void_func\n" +
3064 "%main_lab = OpLabel\n" +
3065 "%2 = OpFOrdNotEqual %bool %double_1 %double_1\n" +
3066 "OpReturn\n" +
3067 "OpFunctionEnd",
3068 2, false),
3069 // Test case 8: fold 1.0 < 1.0
3070 InstructionFoldingCase<bool>(
3071 Header() + "%main = OpFunction %void None %void_func\n" +
3072 "%main_lab = OpLabel\n" +
3073 "%2 = OpFOrdLessThan %bool %double_1 %double_1\n" +
3074 "OpReturn\n" +
3075 "OpFunctionEnd",
3076 2, false),
3077 // Test case 9: fold 1.0 > 1.0
3078 InstructionFoldingCase<bool>(
3079 Header() + "%main = OpFunction %void None %void_func\n" +
3080 "%main_lab = OpLabel\n" +
3081 "%2 = OpFOrdGreaterThan %bool %double_1 %double_1\n" +
3082 "OpReturn\n" +
3083 "OpFunctionEnd",
3084 2, false),
3085 // Test case 10: fold 1.0 <= 1.0
3086 InstructionFoldingCase<bool>(
3087 Header() + "%main = OpFunction %void None %void_func\n" +
3088 "%main_lab = OpLabel\n" +
3089 "%2 = OpFOrdLessThanEqual %bool %double_1 %double_1\n" +
3090 "OpReturn\n" +
3091 "OpFunctionEnd",
3092 2, true),
3093 // Test case 11: fold 1.0 >= 1.0
3094 InstructionFoldingCase<bool>(
3095 Header() + "%main = OpFunction %void None %void_func\n" +
3096 "%main_lab = OpLabel\n" +
3097 "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_1\n" +
3098 "OpReturn\n" +
3099 "OpFunctionEnd",
3100 2, true),
3101 // Test case 12: fold 2.0 < 1.0
3102 InstructionFoldingCase<bool>(
3103 Header() + "%main = OpFunction %void None %void_func\n" +
3104 "%main_lab = OpLabel\n" +
3105 "%2 = OpFOrdLessThan %bool %double_2 %double_1\n" +
3106 "OpReturn\n" +
3107 "OpFunctionEnd",
3108 2, false),
3109 // Test case 13: fold 2.0 > 1.0
3110 InstructionFoldingCase<bool>(
3111 Header() + "%main = OpFunction %void None %void_func\n" +
3112 "%main_lab = OpLabel\n" +
3113 "%2 = OpFOrdGreaterThan %bool %double_2 %double_1\n" +
3114 "OpReturn\n" +
3115 "OpFunctionEnd",
3116 2, true),
3117 // Test case 14: fold 2.0 <= 1.0
3118 InstructionFoldingCase<bool>(
3119 Header() + "%main = OpFunction %void None %void_func\n" +
3120 "%main_lab = OpLabel\n" +
3121 "%2 = OpFOrdLessThanEqual %bool %double_2 %double_1\n" +
3122 "OpReturn\n" +
3123 "OpFunctionEnd",
3124 2, false),
3125 // Test case 15: fold 2.0 >= 1.0
3126 InstructionFoldingCase<bool>(
3127 Header() + "%main = OpFunction %void None %void_func\n" +
3128 "%main_lab = OpLabel\n" +
3129 "%2 = OpFOrdGreaterThanEqual %bool %double_2 %double_1\n" +
3130 "OpReturn\n" +
3131 "OpFunctionEnd",
3132 2, true)
3133 ));
3134
3135 INSTANTIATE_TEST_SUITE_P(DoubleUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3136 ::testing::Values(
3137 // Test case 0: fold 1.0 == 2.0
3138 InstructionFoldingCase<bool>(
3139 Header() + "%main = OpFunction %void None %void_func\n" +
3140 "%main_lab = OpLabel\n" +
3141 "%2 = OpFUnordEqual %bool %double_1 %double_2\n" +
3142 "OpReturn\n" +
3143 "OpFunctionEnd",
3144 2, false),
3145 // Test case 1: fold 1.0 != 2.0
3146 InstructionFoldingCase<bool>(
3147 Header() + "%main = OpFunction %void None %void_func\n" +
3148 "%main_lab = OpLabel\n" +
3149 "%2 = OpFUnordNotEqual %bool %double_1 %double_2\n" +
3150 "OpReturn\n" +
3151 "OpFunctionEnd",
3152 2, true),
3153 // Test case 2: fold 1.0 < 2.0
3154 InstructionFoldingCase<bool>(
3155 Header() + "%main = OpFunction %void None %void_func\n" +
3156 "%main_lab = OpLabel\n" +
3157 "%2 = OpFUnordLessThan %bool %double_1 %double_2\n" +
3158 "OpReturn\n" +
3159 "OpFunctionEnd",
3160 2, true),
3161 // Test case 3: fold 1.0 > 2.0
3162 InstructionFoldingCase<bool>(
3163 Header() + "%main = OpFunction %void None %void_func\n" +
3164 "%main_lab = OpLabel\n" +
3165 "%2 = OpFUnordGreaterThan %bool %double_1 %double_2\n" +
3166 "OpReturn\n" +
3167 "OpFunctionEnd",
3168 2, false),
3169 // Test case 4: fold 1.0 <= 2.0
3170 InstructionFoldingCase<bool>(
3171 Header() + "%main = OpFunction %void None %void_func\n" +
3172 "%main_lab = OpLabel\n" +
3173 "%2 = OpFUnordLessThanEqual %bool %double_1 %double_2\n" +
3174 "OpReturn\n" +
3175 "OpFunctionEnd",
3176 2, true),
3177 // Test case 5: fold 1.0 >= 2.0
3178 InstructionFoldingCase<bool>(
3179 Header() + "%main = OpFunction %void None %void_func\n" +
3180 "%main_lab = OpLabel\n" +
3181 "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_2\n" +
3182 "OpReturn\n" +
3183 "OpFunctionEnd",
3184 2, false),
3185 // Test case 6: fold 1.0 == 1.0
3186 InstructionFoldingCase<bool>(
3187 Header() + "%main = OpFunction %void None %void_func\n" +
3188 "%main_lab = OpLabel\n" +
3189 "%2 = OpFUnordEqual %bool %double_1 %double_1\n" +
3190 "OpReturn\n" +
3191 "OpFunctionEnd",
3192 2, true),
3193 // Test case 7: fold 1.0 != 1.0
3194 InstructionFoldingCase<bool>(
3195 Header() + "%main = OpFunction %void None %void_func\n" +
3196 "%main_lab = OpLabel\n" +
3197 "%2 = OpFUnordNotEqual %bool %double_1 %double_1\n" +
3198 "OpReturn\n" +
3199 "OpFunctionEnd",
3200 2, false),
3201 // Test case 8: fold 1.0 < 1.0
3202 InstructionFoldingCase<bool>(
3203 Header() + "%main = OpFunction %void None %void_func\n" +
3204 "%main_lab = OpLabel\n" +
3205 "%2 = OpFUnordLessThan %bool %double_1 %double_1\n" +
3206 "OpReturn\n" +
3207 "OpFunctionEnd",
3208 2, false),
3209 // Test case 9: fold 1.0 > 1.0
3210 InstructionFoldingCase<bool>(
3211 Header() + "%main = OpFunction %void None %void_func\n" +
3212 "%main_lab = OpLabel\n" +
3213 "%2 = OpFUnordGreaterThan %bool %double_1 %double_1\n" +
3214 "OpReturn\n" +
3215 "OpFunctionEnd",
3216 2, false),
3217 // Test case 10: fold 1.0 <= 1.0
3218 InstructionFoldingCase<bool>(
3219 Header() + "%main = OpFunction %void None %void_func\n" +
3220 "%main_lab = OpLabel\n" +
3221 "%2 = OpFUnordLessThanEqual %bool %double_1 %double_1\n" +
3222 "OpReturn\n" +
3223 "OpFunctionEnd",
3224 2, true),
3225 // Test case 11: fold 1.0 >= 1.0
3226 InstructionFoldingCase<bool>(
3227 Header() + "%main = OpFunction %void None %void_func\n" +
3228 "%main_lab = OpLabel\n" +
3229 "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_1\n" +
3230 "OpReturn\n" +
3231 "OpFunctionEnd",
3232 2, true),
3233 // Test case 12: fold 2.0 < 1.0
3234 InstructionFoldingCase<bool>(
3235 Header() + "%main = OpFunction %void None %void_func\n" +
3236 "%main_lab = OpLabel\n" +
3237 "%2 = OpFUnordLessThan %bool %double_2 %double_1\n" +
3238 "OpReturn\n" +
3239 "OpFunctionEnd",
3240 2, false),
3241 // Test case 13: fold 2.0 > 1.0
3242 InstructionFoldingCase<bool>(
3243 Header() + "%main = OpFunction %void None %void_func\n" +
3244 "%main_lab = OpLabel\n" +
3245 "%2 = OpFUnordGreaterThan %bool %double_2 %double_1\n" +
3246 "OpReturn\n" +
3247 "OpFunctionEnd",
3248 2, true),
3249 // Test case 14: fold 2.0 <= 1.0
3250 InstructionFoldingCase<bool>(
3251 Header() + "%main = OpFunction %void None %void_func\n" +
3252 "%main_lab = OpLabel\n" +
3253 "%2 = OpFUnordLessThanEqual %bool %double_2 %double_1\n" +
3254 "OpReturn\n" +
3255 "OpFunctionEnd",
3256 2, false),
3257 // Test case 15: fold 2.0 >= 1.0
3258 InstructionFoldingCase<bool>(
3259 Header() + "%main = OpFunction %void None %void_func\n" +
3260 "%main_lab = OpLabel\n" +
3261 "%2 = OpFUnordGreaterThanEqual %bool %double_2 %double_1\n" +
3262 "OpReturn\n" +
3263 "OpFunctionEnd",
3264 2, true)
3265 ));
3266
3267 INSTANTIATE_TEST_SUITE_P(FloatOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3268 ::testing::Values(
3269 // Test case 0: fold 1.0 == 2.0
3270 InstructionFoldingCase<bool>(
3271 Header() + "%main = OpFunction %void None %void_func\n" +
3272 "%main_lab = OpLabel\n" +
3273 "%2 = OpFOrdEqual %bool %float_1 %float_2\n" +
3274 "OpReturn\n" +
3275 "OpFunctionEnd",
3276 2, false),
3277 // Test case 1: fold 1.0 != 2.0
3278 InstructionFoldingCase<bool>(
3279 Header() + "%main = OpFunction %void None %void_func\n" +
3280 "%main_lab = OpLabel\n" +
3281 "%2 = OpFOrdNotEqual %bool %float_1 %float_2\n" +
3282 "OpReturn\n" +
3283 "OpFunctionEnd",
3284 2, true),
3285 // Test case 2: fold 1.0 < 2.0
3286 InstructionFoldingCase<bool>(
3287 Header() + "%main = OpFunction %void None %void_func\n" +
3288 "%main_lab = OpLabel\n" +
3289 "%2 = OpFOrdLessThan %bool %float_1 %float_2\n" +
3290 "OpReturn\n" +
3291 "OpFunctionEnd",
3292 2, true),
3293 // Test case 3: fold 1.0 > 2.0
3294 InstructionFoldingCase<bool>(
3295 Header() + "%main = OpFunction %void None %void_func\n" +
3296 "%main_lab = OpLabel\n" +
3297 "%2 = OpFOrdGreaterThan %bool %float_1 %float_2\n" +
3298 "OpReturn\n" +
3299 "OpFunctionEnd",
3300 2, false),
3301 // Test case 4: fold 1.0 <= 2.0
3302 InstructionFoldingCase<bool>(
3303 Header() + "%main = OpFunction %void None %void_func\n" +
3304 "%main_lab = OpLabel\n" +
3305 "%2 = OpFOrdLessThanEqual %bool %float_1 %float_2\n" +
3306 "OpReturn\n" +
3307 "OpFunctionEnd",
3308 2, true),
3309 // Test case 5: fold 1.0 >= 2.0
3310 InstructionFoldingCase<bool>(
3311 Header() + "%main = OpFunction %void None %void_func\n" +
3312 "%main_lab = OpLabel\n" +
3313 "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_2\n" +
3314 "OpReturn\n" +
3315 "OpFunctionEnd",
3316 2, false),
3317 // Test case 6: fold 1.0 == 1.0
3318 InstructionFoldingCase<bool>(
3319 Header() + "%main = OpFunction %void None %void_func\n" +
3320 "%main_lab = OpLabel\n" +
3321 "%2 = OpFOrdEqual %bool %float_1 %float_1\n" +
3322 "OpReturn\n" +
3323 "OpFunctionEnd",
3324 2, true),
3325 // Test case 7: fold 1.0 != 1.0
3326 InstructionFoldingCase<bool>(
3327 Header() + "%main = OpFunction %void None %void_func\n" +
3328 "%main_lab = OpLabel\n" +
3329 "%2 = OpFOrdNotEqual %bool %float_1 %float_1\n" +
3330 "OpReturn\n" +
3331 "OpFunctionEnd",
3332 2, false),
3333 // Test case 8: fold 1.0 < 1.0
3334 InstructionFoldingCase<bool>(
3335 Header() + "%main = OpFunction %void None %void_func\n" +
3336 "%main_lab = OpLabel\n" +
3337 "%2 = OpFOrdLessThan %bool %float_1 %float_1\n" +
3338 "OpReturn\n" +
3339 "OpFunctionEnd",
3340 2, false),
3341 // Test case 9: fold 1.0 > 1.0
3342 InstructionFoldingCase<bool>(
3343 Header() + "%main = OpFunction %void None %void_func\n" +
3344 "%main_lab = OpLabel\n" +
3345 "%2 = OpFOrdGreaterThan %bool %float_1 %float_1\n" +
3346 "OpReturn\n" +
3347 "OpFunctionEnd",
3348 2, false),
3349 // Test case 10: fold 1.0 <= 1.0
3350 InstructionFoldingCase<bool>(
3351 Header() + "%main = OpFunction %void None %void_func\n" +
3352 "%main_lab = OpLabel\n" +
3353 "%2 = OpFOrdLessThanEqual %bool %float_1 %float_1\n" +
3354 "OpReturn\n" +
3355 "OpFunctionEnd",
3356 2, true),
3357 // Test case 11: fold 1.0 >= 1.0
3358 InstructionFoldingCase<bool>(
3359 Header() + "%main = OpFunction %void None %void_func\n" +
3360 "%main_lab = OpLabel\n" +
3361 "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_1\n" +
3362 "OpReturn\n" +
3363 "OpFunctionEnd",
3364 2, true),
3365 // Test case 12: fold 2.0 < 1.0
3366 InstructionFoldingCase<bool>(
3367 Header() + "%main = OpFunction %void None %void_func\n" +
3368 "%main_lab = OpLabel\n" +
3369 "%2 = OpFOrdLessThan %bool %float_2 %float_1\n" +
3370 "OpReturn\n" +
3371 "OpFunctionEnd",
3372 2, false),
3373 // Test case 13: fold 2.0 > 1.0
3374 InstructionFoldingCase<bool>(
3375 Header() + "%main = OpFunction %void None %void_func\n" +
3376 "%main_lab = OpLabel\n" +
3377 "%2 = OpFOrdGreaterThan %bool %float_2 %float_1\n" +
3378 "OpReturn\n" +
3379 "OpFunctionEnd",
3380 2, true),
3381 // Test case 14: fold 2.0 <= 1.0
3382 InstructionFoldingCase<bool>(
3383 Header() + "%main = OpFunction %void None %void_func\n" +
3384 "%main_lab = OpLabel\n" +
3385 "%2 = OpFOrdLessThanEqual %bool %float_2 %float_1\n" +
3386 "OpReturn\n" +
3387 "OpFunctionEnd",
3388 2, false),
3389 // Test case 15: fold 2.0 >= 1.0
3390 InstructionFoldingCase<bool>(
3391 Header() + "%main = OpFunction %void None %void_func\n" +
3392 "%main_lab = OpLabel\n" +
3393 "%2 = OpFOrdGreaterThanEqual %bool %float_2 %float_1\n" +
3394 "OpReturn\n" +
3395 "OpFunctionEnd",
3396 2, true)
3397 ));
3398
3399 INSTANTIATE_TEST_SUITE_P(FloatUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3400 ::testing::Values(
3401 // Test case 0: fold 1.0 == 2.0
3402 InstructionFoldingCase<bool>(
3403 Header() + "%main = OpFunction %void None %void_func\n" +
3404 "%main_lab = OpLabel\n" +
3405 "%2 = OpFUnordEqual %bool %float_1 %float_2\n" +
3406 "OpReturn\n" +
3407 "OpFunctionEnd",
3408 2, false),
3409 // Test case 1: fold 1.0 != 2.0
3410 InstructionFoldingCase<bool>(
3411 Header() + "%main = OpFunction %void None %void_func\n" +
3412 "%main_lab = OpLabel\n" +
3413 "%2 = OpFUnordNotEqual %bool %float_1 %float_2\n" +
3414 "OpReturn\n" +
3415 "OpFunctionEnd",
3416 2, true),
3417 // Test case 2: fold 1.0 < 2.0
3418 InstructionFoldingCase<bool>(
3419 Header() + "%main = OpFunction %void None %void_func\n" +
3420 "%main_lab = OpLabel\n" +
3421 "%2 = OpFUnordLessThan %bool %float_1 %float_2\n" +
3422 "OpReturn\n" +
3423 "OpFunctionEnd",
3424 2, true),
3425 // Test case 3: fold 1.0 > 2.0
3426 InstructionFoldingCase<bool>(
3427 Header() + "%main = OpFunction %void None %void_func\n" +
3428 "%main_lab = OpLabel\n" +
3429 "%2 = OpFUnordGreaterThan %bool %float_1 %float_2\n" +
3430 "OpReturn\n" +
3431 "OpFunctionEnd",
3432 2, false),
3433 // Test case 4: fold 1.0 <= 2.0
3434 InstructionFoldingCase<bool>(
3435 Header() + "%main = OpFunction %void None %void_func\n" +
3436 "%main_lab = OpLabel\n" +
3437 "%2 = OpFUnordLessThanEqual %bool %float_1 %float_2\n" +
3438 "OpReturn\n" +
3439 "OpFunctionEnd",
3440 2, true),
3441 // Test case 5: fold 1.0 >= 2.0
3442 InstructionFoldingCase<bool>(
3443 Header() + "%main = OpFunction %void None %void_func\n" +
3444 "%main_lab = OpLabel\n" +
3445 "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_2\n" +
3446 "OpReturn\n" +
3447 "OpFunctionEnd",
3448 2, false),
3449 // Test case 6: fold 1.0 == 1.0
3450 InstructionFoldingCase<bool>(
3451 Header() + "%main = OpFunction %void None %void_func\n" +
3452 "%main_lab = OpLabel\n" +
3453 "%2 = OpFUnordEqual %bool %float_1 %float_1\n" +
3454 "OpReturn\n" +
3455 "OpFunctionEnd",
3456 2, true),
3457 // Test case 7: fold 1.0 != 1.0
3458 InstructionFoldingCase<bool>(
3459 Header() + "%main = OpFunction %void None %void_func\n" +
3460 "%main_lab = OpLabel\n" +
3461 "%2 = OpFUnordNotEqual %bool %float_1 %float_1\n" +
3462 "OpReturn\n" +
3463 "OpFunctionEnd",
3464 2, false),
3465 // Test case 8: fold 1.0 < 1.0
3466 InstructionFoldingCase<bool>(
3467 Header() + "%main = OpFunction %void None %void_func\n" +
3468 "%main_lab = OpLabel\n" +
3469 "%2 = OpFUnordLessThan %bool %float_1 %float_1\n" +
3470 "OpReturn\n" +
3471 "OpFunctionEnd",
3472 2, false),
3473 // Test case 9: fold 1.0 > 1.0
3474 InstructionFoldingCase<bool>(
3475 Header() + "%main = OpFunction %void None %void_func\n" +
3476 "%main_lab = OpLabel\n" +
3477 "%2 = OpFUnordGreaterThan %bool %float_1 %float_1\n" +
3478 "OpReturn\n" +
3479 "OpFunctionEnd",
3480 2, false),
3481 // Test case 10: fold 1.0 <= 1.0
3482 InstructionFoldingCase<bool>(
3483 Header() + "%main = OpFunction %void None %void_func\n" +
3484 "%main_lab = OpLabel\n" +
3485 "%2 = OpFUnordLessThanEqual %bool %float_1 %float_1\n" +
3486 "OpReturn\n" +
3487 "OpFunctionEnd",
3488 2, true),
3489 // Test case 11: fold 1.0 >= 1.0
3490 InstructionFoldingCase<bool>(
3491 Header() + "%main = OpFunction %void None %void_func\n" +
3492 "%main_lab = OpLabel\n" +
3493 "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_1\n" +
3494 "OpReturn\n" +
3495 "OpFunctionEnd",
3496 2, true),
3497 // Test case 12: fold 2.0 < 1.0
3498 InstructionFoldingCase<bool>(
3499 Header() + "%main = OpFunction %void None %void_func\n" +
3500 "%main_lab = OpLabel\n" +
3501 "%2 = OpFUnordLessThan %bool %float_2 %float_1\n" +
3502 "OpReturn\n" +
3503 "OpFunctionEnd",
3504 2, false),
3505 // Test case 13: fold 2.0 > 1.0
3506 InstructionFoldingCase<bool>(
3507 Header() + "%main = OpFunction %void None %void_func\n" +
3508 "%main_lab = OpLabel\n" +
3509 "%2 = OpFUnordGreaterThan %bool %float_2 %float_1\n" +
3510 "OpReturn\n" +
3511 "OpFunctionEnd",
3512 2, true),
3513 // Test case 14: fold 2.0 <= 1.0
3514 InstructionFoldingCase<bool>(
3515 Header() + "%main = OpFunction %void None %void_func\n" +
3516 "%main_lab = OpLabel\n" +
3517 "%2 = OpFUnordLessThanEqual %bool %float_2 %float_1\n" +
3518 "OpReturn\n" +
3519 "OpFunctionEnd",
3520 2, false),
3521 // Test case 15: fold 2.0 >= 1.0
3522 InstructionFoldingCase<bool>(
3523 Header() + "%main = OpFunction %void None %void_func\n" +
3524 "%main_lab = OpLabel\n" +
3525 "%2 = OpFUnordGreaterThanEqual %bool %float_2 %float_1\n" +
3526 "OpReturn\n" +
3527 "OpFunctionEnd",
3528 2, true)
3529 ));
3530
3531 INSTANTIATE_TEST_SUITE_P(DoubleNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3532 ::testing::Values(
3533 // Test case 0: fold NaN == 0 (ord)
3534 InstructionFoldingCase<bool>(
3535 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3536 "%main_lab = OpLabel\n" +
3537 "%2 = OpFOrdEqual %bool %double_nan %double_0\n" +
3538 "OpReturn\n" +
3539 "OpFunctionEnd",
3540 2, false),
3541 // Test case 1: fold NaN == NaN (unord)
3542 InstructionFoldingCase<bool>(
3543 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3544 "%main_lab = OpLabel\n" +
3545 "%2 = OpFUnordEqual %bool %double_nan %double_0\n" +
3546 "OpReturn\n" +
3547 "OpFunctionEnd",
3548 2, true),
3549 // Test case 2: fold NaN != NaN (ord)
3550 InstructionFoldingCase<bool>(
3551 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3552 "%main_lab = OpLabel\n" +
3553 "%2 = OpFOrdNotEqual %bool %double_nan %double_0\n" +
3554 "OpReturn\n" +
3555 "OpFunctionEnd",
3556 2, false),
3557 // Test case 3: fold NaN != NaN (unord)
3558 InstructionFoldingCase<bool>(
3559 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3560 "%main_lab = OpLabel\n" +
3561 "%2 = OpFUnordNotEqual %bool %double_nan %double_0\n" +
3562 "OpReturn\n" +
3563 "OpFunctionEnd",
3564 2, true)
3565 ));
3566
3567 INSTANTIATE_TEST_SUITE_P(FloatNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest,
3568 ::testing::Values(
3569 // Test case 0: fold NaN == 0 (ord)
3570 InstructionFoldingCase<bool>(
3571 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3572 "%main_lab = OpLabel\n" +
3573 "%2 = OpFOrdEqual %bool %float_nan %float_0\n" +
3574 "OpReturn\n" +
3575 "OpFunctionEnd",
3576 2, false),
3577 // Test case 1: fold NaN == NaN (unord)
3578 InstructionFoldingCase<bool>(
3579 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3580 "%main_lab = OpLabel\n" +
3581 "%2 = OpFUnordEqual %bool %float_nan %float_0\n" +
3582 "OpReturn\n" +
3583 "OpFunctionEnd",
3584 2, true),
3585 // Test case 2: fold NaN != NaN (ord)
3586 InstructionFoldingCase<bool>(
3587 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3588 "%main_lab = OpLabel\n" +
3589 "%2 = OpFOrdNotEqual %bool %float_nan %float_0\n" +
3590 "OpReturn\n" +
3591 "OpFunctionEnd",
3592 2, false),
3593 // Test case 3: fold NaN != NaN (unord)
3594 InstructionFoldingCase<bool>(
3595 HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" +
3596 "%main_lab = OpLabel\n" +
3597 "%2 = OpFUnordNotEqual %bool %float_nan %float_0\n" +
3598 "OpReturn\n" +
3599 "OpFunctionEnd",
3600 2, true)
3601 ));
3602 // clang-format on
3603
3604 template <class ResultType>
3605 struct InstructionFoldingCaseWithMap {
InstructionFoldingCaseWithMapspvtools::opt::__anonb0a5c4000111::InstructionFoldingCaseWithMap3606 InstructionFoldingCaseWithMap(const std::string& tb, uint32_t id,
3607 ResultType result,
3608 std::function<uint32_t(uint32_t)> map)
3609 : test_body(tb), id_to_fold(id), expected_result(result), id_map(map) {}
3610
3611 std::string test_body;
3612 uint32_t id_to_fold;
3613 ResultType expected_result;
3614 std::function<uint32_t(uint32_t)> id_map;
3615 };
3616
3617 using IntegerInstructionFoldingTestWithMap =
3618 ::testing::TestWithParam<InstructionFoldingCaseWithMap<uint32_t>>;
3619
TEST_P(IntegerInstructionFoldingTestWithMap,Case)3620 TEST_P(IntegerInstructionFoldingTestWithMap, Case) {
3621 const auto& tc = GetParam();
3622
3623 std::unique_ptr<IRContext> context;
3624 Instruction* inst;
3625 std::tie(context, inst) =
3626 GetInstructionToFold(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_5);
3627
3628 inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
3629 tc.id_map);
3630 EXPECT_NE(inst, nullptr);
3631
3632 CheckForExpectedScalarConstant(inst, tc.expected_result,
3633 [](const analysis::Constant* c) {
3634 return c->AsIntConstant()->GetU32BitValue();
3635 });
3636 }
3637 // clang-format off
3638
3639 INSTANTIATE_TEST_SUITE_P(TestCase, IntegerInstructionFoldingTestWithMap,
3640 ::testing::Values(
3641 // Test case 0: fold %3 = 0; %3 * n
3642 InstructionFoldingCaseWithMap<uint32_t>(
3643 Header() + "%main = OpFunction %void None %void_func\n" +
3644 "%main_lab = OpLabel\n" +
3645 "%n = OpVariable %_ptr_int Function\n" +
3646 "%load = OpLoad %int %n\n" +
3647 "%3 = OpCopyObject %int %int_0\n"
3648 "%2 = OpIMul %int %3 %load\n" +
3649 "OpReturn\n" +
3650 "OpFunctionEnd",
__anonb0a5c4000d02(uint32_t id) 3651 2, 0, [](uint32_t id) {return (id == 3 ? INT_0_ID : id);})
3652 ));
3653 // clang-format on
3654
3655 using BooleanInstructionFoldingTestWithMap =
3656 ::testing::TestWithParam<InstructionFoldingCaseWithMap<bool>>;
3657
TEST_P(BooleanInstructionFoldingTestWithMap,Case)3658 TEST_P(BooleanInstructionFoldingTestWithMap, Case) {
3659 const auto& tc = GetParam();
3660
3661 std::unique_ptr<IRContext> context;
3662 Instruction* inst;
3663 std::tie(context, inst) =
3664 GetInstructionToFold(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_5);
3665 inst = context->get_instruction_folder().FoldInstructionToConstant(inst,
3666 tc.id_map);
3667 ASSERT_NE(inst, nullptr);
3668 CheckForExpectedScalarConstant(
3669 inst, tc.expected_result,
3670 [](const analysis::Constant* c) { return c->AsBoolConstant()->value(); });
3671 }
3672
3673 // clang-format off
3674 INSTANTIATE_TEST_SUITE_P(TestCase, BooleanInstructionFoldingTestWithMap,
3675 ::testing::Values(
3676 // Test case 0: fold %3 = true; %3 || n
3677 InstructionFoldingCaseWithMap<bool>(
3678 Header() + "%main = OpFunction %void None %void_func\n" +
3679 "%main_lab = OpLabel\n" +
3680 "%n = OpVariable %_ptr_bool Function\n" +
3681 "%load = OpLoad %bool %n\n" +
3682 "%3 = OpCopyObject %bool %true\n" +
3683 "%2 = OpLogicalOr %bool %3 %load\n" +
3684 "OpReturn\n" +
3685 "OpFunctionEnd",
__anonb0a5c4000f02(uint32_t id) 3686 2, true, [](uint32_t id) {return (id == 3 ? TRUE_ID : id);})
3687 ));
3688 // clang-format on
3689
3690 using GeneralInstructionFoldingTest =
3691 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
3692
TEST_P(GeneralInstructionFoldingTest,Case)3693 TEST_P(GeneralInstructionFoldingTest, Case) {
3694 const auto& tc = GetParam();
3695
3696 std::unique_ptr<IRContext> context;
3697 Instruction* inst;
3698 std::tie(context, inst) =
3699 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
3700
3701 EXPECT_TRUE((inst == nullptr) == (tc.expected_result == 0));
3702 if (inst != nullptr) {
3703 EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
3704 EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
3705 }
3706 }
3707
3708 // clang-format off
3709 INSTANTIATE_TEST_SUITE_P(IntegerArithmeticTestCases, GeneralInstructionFoldingTest,
3710 ::testing::Values(
3711 // Test case 0: Don't fold n * m
3712 InstructionFoldingCase<uint32_t>(
3713 Header() + "%main = OpFunction %void None %void_func\n" +
3714 "%main_lab = OpLabel\n" +
3715 "%n = OpVariable %_ptr_int Function\n" +
3716 "%m = OpVariable %_ptr_int Function\n" +
3717 "%load_n = OpLoad %int %n\n" +
3718 "%load_m = OpLoad %int %m\n" +
3719 "%2 = OpIMul %int %load_n %load_m\n" +
3720 "OpReturn\n" +
3721 "OpFunctionEnd",
3722 2, 0),
3723 // Test case 1: Don't fold n / m (unsigned)
3724 InstructionFoldingCase<uint32_t>(
3725 Header() + "%main = OpFunction %void None %void_func\n" +
3726 "%main_lab = OpLabel\n" +
3727 "%n = OpVariable %_ptr_uint Function\n" +
3728 "%m = OpVariable %_ptr_uint Function\n" +
3729 "%load_n = OpLoad %uint %n\n" +
3730 "%load_m = OpLoad %uint %m\n" +
3731 "%2 = OpUDiv %uint %load_n %load_m\n" +
3732 "OpReturn\n" +
3733 "OpFunctionEnd",
3734 2, 0),
3735 // Test case 2: Don't fold n / m (signed)
3736 InstructionFoldingCase<uint32_t>(
3737 Header() + "%main = OpFunction %void None %void_func\n" +
3738 "%main_lab = OpLabel\n" +
3739 "%n = OpVariable %_ptr_int Function\n" +
3740 "%m = OpVariable %_ptr_int Function\n" +
3741 "%load_n = OpLoad %int %n\n" +
3742 "%load_m = OpLoad %int %m\n" +
3743 "%2 = OpSDiv %int %load_n %load_m\n" +
3744 "OpReturn\n" +
3745 "OpFunctionEnd",
3746 2, 0),
3747 // Test case 3: Don't fold n remainder m
3748 InstructionFoldingCase<uint32_t>(
3749 Header() + "%main = OpFunction %void None %void_func\n" +
3750 "%main_lab = OpLabel\n" +
3751 "%n = OpVariable %_ptr_int Function\n" +
3752 "%m = OpVariable %_ptr_int Function\n" +
3753 "%load_n = OpLoad %int %n\n" +
3754 "%load_m = OpLoad %int %m\n" +
3755 "%2 = OpSRem %int %load_n %load_m\n" +
3756 "OpReturn\n" +
3757 "OpFunctionEnd",
3758 2, 0),
3759 // Test case 4: Don't fold n % m (signed)
3760 InstructionFoldingCase<uint32_t>(
3761 Header() + "%main = OpFunction %void None %void_func\n" +
3762 "%main_lab = OpLabel\n" +
3763 "%n = OpVariable %_ptr_int Function\n" +
3764 "%m = OpVariable %_ptr_int Function\n" +
3765 "%load_n = OpLoad %int %n\n" +
3766 "%load_m = OpLoad %int %m\n" +
3767 "%2 = OpSMod %int %load_n %load_m\n" +
3768 "OpReturn\n" +
3769 "OpFunctionEnd",
3770 2, 0),
3771 // Test case 5: Don't fold n % m (unsigned)
3772 InstructionFoldingCase<uint32_t>(
3773 Header() + "%main = OpFunction %void None %void_func\n" +
3774 "%main_lab = OpLabel\n" +
3775 "%n = OpVariable %_ptr_uint Function\n" +
3776 "%m = OpVariable %_ptr_uint Function\n" +
3777 "%load_n = OpLoad %uint %n\n" +
3778 "%load_m = OpLoad %uint %m\n" +
3779 "%2 = OpUMod %int %load_n %load_m\n" +
3780 "OpReturn\n" +
3781 "OpFunctionEnd",
3782 2, 0),
3783 // Test case 6: Don't fold n << m
3784 InstructionFoldingCase<uint32_t>(
3785 Header() + "%main = OpFunction %void None %void_func\n" +
3786 "%main_lab = OpLabel\n" +
3787 "%n = OpVariable %_ptr_uint Function\n" +
3788 "%m = OpVariable %_ptr_uint Function\n" +
3789 "%load_n = OpLoad %uint %n\n" +
3790 "%load_m = OpLoad %uint %m\n" +
3791 "%2 = OpShiftRightLogical %int %load_n %load_m\n" +
3792 "OpReturn\n" +
3793 "OpFunctionEnd",
3794 2, 0),
3795 // Test case 7: Don't fold n >> m
3796 InstructionFoldingCase<uint32_t>(
3797 Header() + "%main = OpFunction %void None %void_func\n" +
3798 "%main_lab = OpLabel\n" +
3799 "%n = OpVariable %_ptr_uint Function\n" +
3800 "%m = OpVariable %_ptr_uint Function\n" +
3801 "%load_n = OpLoad %uint %n\n" +
3802 "%load_m = OpLoad %uint %m\n" +
3803 "%2 = OpShiftLeftLogical %int %load_n %load_m\n" +
3804 "OpReturn\n" +
3805 "OpFunctionEnd",
3806 2, 0),
3807 // Test case 8: Don't fold n | m
3808 InstructionFoldingCase<uint32_t>(
3809 Header() + "%main = OpFunction %void None %void_func\n" +
3810 "%main_lab = OpLabel\n" +
3811 "%n = OpVariable %_ptr_uint Function\n" +
3812 "%m = OpVariable %_ptr_uint Function\n" +
3813 "%load_n = OpLoad %uint %n\n" +
3814 "%load_m = OpLoad %uint %m\n" +
3815 "%2 = OpBitwiseOr %int %load_n %load_m\n" +
3816 "OpReturn\n" +
3817 "OpFunctionEnd",
3818 2, 0),
3819 // Test case 9: Don't fold n & m
3820 InstructionFoldingCase<uint32_t>(
3821 Header() + "%main = OpFunction %void None %void_func\n" +
3822 "%main_lab = OpLabel\n" +
3823 "%n = OpVariable %_ptr_uint Function\n" +
3824 "%m = OpVariable %_ptr_uint Function\n" +
3825 "%load_n = OpLoad %uint %n\n" +
3826 "%load_m = OpLoad %uint %m\n" +
3827 "%2 = OpBitwiseAnd %int %load_n %load_m\n" +
3828 "OpReturn\n" +
3829 "OpFunctionEnd",
3830 2, 0),
3831 // Test case 10: Don't fold n < m (unsigned)
3832 InstructionFoldingCase<uint32_t>(
3833 Header() + "%main = OpFunction %void None %void_func\n" +
3834 "%main_lab = OpLabel\n" +
3835 "%n = OpVariable %_ptr_uint Function\n" +
3836 "%m = OpVariable %_ptr_uint Function\n" +
3837 "%load_n = OpLoad %uint %n\n" +
3838 "%load_m = OpLoad %uint %m\n" +
3839 "%2 = OpULessThan %bool %load_n %load_m\n" +
3840 "OpReturn\n" +
3841 "OpFunctionEnd",
3842 2, 0),
3843 // Test case 11: Don't fold n > m (unsigned)
3844 InstructionFoldingCase<uint32_t>(
3845 Header() + "%main = OpFunction %void None %void_func\n" +
3846 "%main_lab = OpLabel\n" +
3847 "%n = OpVariable %_ptr_uint Function\n" +
3848 "%m = OpVariable %_ptr_uint Function\n" +
3849 "%load_n = OpLoad %uint %n\n" +
3850 "%load_m = OpLoad %uint %m\n" +
3851 "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
3852 "OpReturn\n" +
3853 "OpFunctionEnd",
3854 2, 0),
3855 // Test case 12: Don't fold n <= m (unsigned)
3856 InstructionFoldingCase<uint32_t>(
3857 Header() + "%main = OpFunction %void None %void_func\n" +
3858 "%main_lab = OpLabel\n" +
3859 "%n = OpVariable %_ptr_uint Function\n" +
3860 "%m = OpVariable %_ptr_uint Function\n" +
3861 "%load_n = OpLoad %uint %n\n" +
3862 "%load_m = OpLoad %uint %m\n" +
3863 "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
3864 "OpReturn\n" +
3865 "OpFunctionEnd",
3866 2, 0),
3867 // Test case 13: Don't fold n >= m (unsigned)
3868 InstructionFoldingCase<uint32_t>(
3869 Header() + "%main = OpFunction %void None %void_func\n" +
3870 "%main_lab = OpLabel\n" +
3871 "%n = OpVariable %_ptr_uint Function\n" +
3872 "%m = OpVariable %_ptr_uint Function\n" +
3873 "%load_n = OpLoad %uint %n\n" +
3874 "%load_m = OpLoad %uint %m\n" +
3875 "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
3876 "OpReturn\n" +
3877 "OpFunctionEnd",
3878 2, 0),
3879 // Test case 14: Don't fold n < m (signed)
3880 InstructionFoldingCase<uint32_t>(
3881 Header() + "%main = OpFunction %void None %void_func\n" +
3882 "%main_lab = OpLabel\n" +
3883 "%n = OpVariable %_ptr_int Function\n" +
3884 "%m = OpVariable %_ptr_int Function\n" +
3885 "%load_n = OpLoad %int %n\n" +
3886 "%load_m = OpLoad %int %m\n" +
3887 "%2 = OpULessThan %bool %load_n %load_m\n" +
3888 "OpReturn\n" +
3889 "OpFunctionEnd",
3890 2, 0),
3891 // Test case 15: Don't fold n > m (signed)
3892 InstructionFoldingCase<uint32_t>(
3893 Header() + "%main = OpFunction %void None %void_func\n" +
3894 "%main_lab = OpLabel\n" +
3895 "%n = OpVariable %_ptr_int Function\n" +
3896 "%m = OpVariable %_ptr_int Function\n" +
3897 "%load_n = OpLoad %int %n\n" +
3898 "%load_m = OpLoad %int %m\n" +
3899 "%2 = OpUGreaterThan %bool %load_n %load_m\n" +
3900 "OpReturn\n" +
3901 "OpFunctionEnd",
3902 2, 0),
3903 // Test case 16: Don't fold n <= m (signed)
3904 InstructionFoldingCase<uint32_t>(
3905 Header() + "%main = OpFunction %void None %void_func\n" +
3906 "%main_lab = OpLabel\n" +
3907 "%n = OpVariable %_ptr_int Function\n" +
3908 "%m = OpVariable %_ptr_int Function\n" +
3909 "%load_n = OpLoad %int %n\n" +
3910 "%load_m = OpLoad %int %m\n" +
3911 "%2 = OpULessThanEqual %bool %load_n %load_m\n" +
3912 "OpReturn\n" +
3913 "OpFunctionEnd",
3914 2, 0),
3915 // Test case 17: Don't fold n >= m (signed)
3916 InstructionFoldingCase<uint32_t>(
3917 Header() + "%main = OpFunction %void None %void_func\n" +
3918 "%main_lab = OpLabel\n" +
3919 "%n = OpVariable %_ptr_int Function\n" +
3920 "%m = OpVariable %_ptr_int Function\n" +
3921 "%load_n = OpLoad %int %n\n" +
3922 "%load_m = OpLoad %int %m\n" +
3923 "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" +
3924 "OpReturn\n" +
3925 "OpFunctionEnd",
3926 2, 0),
3927 // Test case 18: Don't fold n || m
3928 InstructionFoldingCase<uint32_t>(
3929 Header() + "%main = OpFunction %void None %void_func\n" +
3930 "%main_lab = OpLabel\n" +
3931 "%n = OpVariable %_ptr_bool Function\n" +
3932 "%m = OpVariable %_ptr_bool Function\n" +
3933 "%load_n = OpLoad %bool %n\n" +
3934 "%load_m = OpLoad %bool %m\n" +
3935 "%2 = OpLogicalOr %bool %load_n %load_m\n" +
3936 "OpReturn\n" +
3937 "OpFunctionEnd",
3938 2, 0),
3939 // Test case 19: Don't fold n && m
3940 InstructionFoldingCase<uint32_t>(
3941 Header() + "%main = OpFunction %void None %void_func\n" +
3942 "%main_lab = OpLabel\n" +
3943 "%n = OpVariable %_ptr_bool Function\n" +
3944 "%m = OpVariable %_ptr_bool Function\n" +
3945 "%load_n = OpLoad %bool %n\n" +
3946 "%load_m = OpLoad %bool %m\n" +
3947 "%2 = OpLogicalAnd %bool %load_n %load_m\n" +
3948 "OpReturn\n" +
3949 "OpFunctionEnd",
3950 2, 0),
3951 // Test case 20: Don't fold n * 3
3952 InstructionFoldingCase<uint32_t>(
3953 Header() + "%main = OpFunction %void None %void_func\n" +
3954 "%main_lab = OpLabel\n" +
3955 "%n = OpVariable %_ptr_int Function\n" +
3956 "%load_n = OpLoad %int %n\n" +
3957 "%2 = OpIMul %int %load_n %int_3\n" +
3958 "OpReturn\n" +
3959 "OpFunctionEnd",
3960 2, 0),
3961 // Test case 21: Don't fold n / 3 (unsigned)
3962 InstructionFoldingCase<uint32_t>(
3963 Header() + "%main = OpFunction %void None %void_func\n" +
3964 "%main_lab = OpLabel\n" +
3965 "%n = OpVariable %_ptr_uint Function\n" +
3966 "%load_n = OpLoad %uint %n\n" +
3967 "%2 = OpUDiv %uint %load_n %uint_3\n" +
3968 "OpReturn\n" +
3969 "OpFunctionEnd",
3970 2, 0),
3971 // Test case 22: Don't fold n / 3 (signed)
3972 InstructionFoldingCase<uint32_t>(
3973 Header() + "%main = OpFunction %void None %void_func\n" +
3974 "%main_lab = OpLabel\n" +
3975 "%n = OpVariable %_ptr_int Function\n" +
3976 "%load_n = OpLoad %int %n\n" +
3977 "%2 = OpSDiv %int %load_n %int_3\n" +
3978 "OpReturn\n" +
3979 "OpFunctionEnd",
3980 2, 0),
3981 // Test case 23: Don't fold n remainder 3
3982 InstructionFoldingCase<uint32_t>(
3983 Header() + "%main = OpFunction %void None %void_func\n" +
3984 "%main_lab = OpLabel\n" +
3985 "%n = OpVariable %_ptr_int Function\n" +
3986 "%load_n = OpLoad %int %n\n" +
3987 "%2 = OpSRem %int %load_n %int_3\n" +
3988 "OpReturn\n" +
3989 "OpFunctionEnd",
3990 2, 0),
3991 // Test case 24: Don't fold n % 3 (signed)
3992 InstructionFoldingCase<uint32_t>(
3993 Header() + "%main = OpFunction %void None %void_func\n" +
3994 "%main_lab = OpLabel\n" +
3995 "%n = OpVariable %_ptr_int Function\n" +
3996 "%load_n = OpLoad %int %n\n" +
3997 "%2 = OpSMod %int %load_n %int_3\n" +
3998 "OpReturn\n" +
3999 "OpFunctionEnd",
4000 2, 0),
4001 // Test case 25: Don't fold n % 3 (unsigned)
4002 InstructionFoldingCase<uint32_t>(
4003 Header() + "%main = OpFunction %void None %void_func\n" +
4004 "%main_lab = OpLabel\n" +
4005 "%n = OpVariable %_ptr_uint Function\n" +
4006 "%load_n = OpLoad %uint %n\n" +
4007 "%2 = OpUMod %int %load_n %int_3\n" +
4008 "OpReturn\n" +
4009 "OpFunctionEnd",
4010 2, 0),
4011 // Test case 26: Don't fold n << 3
4012 InstructionFoldingCase<uint32_t>(
4013 Header() + "%main = OpFunction %void None %void_func\n" +
4014 "%main_lab = OpLabel\n" +
4015 "%n = OpVariable %_ptr_uint Function\n" +
4016 "%load_n = OpLoad %uint %n\n" +
4017 "%2 = OpShiftRightLogical %int %load_n %int_3\n" +
4018 "OpReturn\n" +
4019 "OpFunctionEnd",
4020 2, 0),
4021 // Test case 27: Don't fold n >> 3
4022 InstructionFoldingCase<uint32_t>(
4023 Header() + "%main = OpFunction %void None %void_func\n" +
4024 "%main_lab = OpLabel\n" +
4025 "%n = OpVariable %_ptr_uint Function\n" +
4026 "%load_n = OpLoad %uint %n\n" +
4027 "%2 = OpShiftLeftLogical %int %load_n %int_3\n" +
4028 "OpReturn\n" +
4029 "OpFunctionEnd",
4030 2, 0),
4031 // Test case 28: Don't fold n | 3
4032 InstructionFoldingCase<uint32_t>(
4033 Header() + "%main = OpFunction %void None %void_func\n" +
4034 "%main_lab = OpLabel\n" +
4035 "%n = OpVariable %_ptr_uint Function\n" +
4036 "%load_n = OpLoad %uint %n\n" +
4037 "%2 = OpBitwiseOr %int %load_n %int_3\n" +
4038 "OpReturn\n" +
4039 "OpFunctionEnd",
4040 2, 0),
4041 // Test case 29: Don't fold n & 3
4042 InstructionFoldingCase<uint32_t>(
4043 Header() + "%main = OpFunction %void None %void_func\n" +
4044 "%main_lab = OpLabel\n" +
4045 "%n = OpVariable %_ptr_uint Function\n" +
4046 "%load_n = OpLoad %uint %n\n" +
4047 "%2 = OpBitwiseAnd %uint %load_n %uint_3\n" +
4048 "OpReturn\n" +
4049 "OpFunctionEnd",
4050 2, 0),
4051 // Test case 30: Don't fold n < 3 (unsigned)
4052 InstructionFoldingCase<uint32_t>(
4053 Header() + "%main = OpFunction %void None %void_func\n" +
4054 "%main_lab = OpLabel\n" +
4055 "%n = OpVariable %_ptr_uint Function\n" +
4056 "%load_n = OpLoad %uint %n\n" +
4057 "%2 = OpULessThan %bool %load_n %uint_3\n" +
4058 "OpReturn\n" +
4059 "OpFunctionEnd",
4060 2, 0),
4061 // Test case 31: Don't fold n > 3 (unsigned)
4062 InstructionFoldingCase<uint32_t>(
4063 Header() + "%main = OpFunction %void None %void_func\n" +
4064 "%main_lab = OpLabel\n" +
4065 "%n = OpVariable %_ptr_uint Function\n" +
4066 "%load_n = OpLoad %uint %n\n" +
4067 "%2 = OpUGreaterThan %bool %load_n %uint_3\n" +
4068 "OpReturn\n" +
4069 "OpFunctionEnd",
4070 2, 0),
4071 // Test case 32: Don't fold n <= 3 (unsigned)
4072 InstructionFoldingCase<uint32_t>(
4073 Header() + "%main = OpFunction %void None %void_func\n" +
4074 "%main_lab = OpLabel\n" +
4075 "%n = OpVariable %_ptr_uint Function\n" +
4076 "%load_n = OpLoad %uint %n\n" +
4077 "%2 = OpULessThanEqual %bool %load_n %uint_3\n" +
4078 "OpReturn\n" +
4079 "OpFunctionEnd",
4080 2, 0),
4081 // Test case 33: Don't fold n >= 3 (unsigned)
4082 InstructionFoldingCase<uint32_t>(
4083 Header() + "%main = OpFunction %void None %void_func\n" +
4084 "%main_lab = OpLabel\n" +
4085 "%n = OpVariable %_ptr_uint Function\n" +
4086 "%load_n = OpLoad %uint %n\n" +
4087 "%2 = OpUGreaterThanEqual %bool %load_n %uint_3\n" +
4088 "OpReturn\n" +
4089 "OpFunctionEnd",
4090 2, 0),
4091 // Test case 34: Don't fold n < 3 (signed)
4092 InstructionFoldingCase<uint32_t>(
4093 Header() + "%main = OpFunction %void None %void_func\n" +
4094 "%main_lab = OpLabel\n" +
4095 "%n = OpVariable %_ptr_int Function\n" +
4096 "%load_n = OpLoad %int %n\n" +
4097 "%2 = OpULessThan %bool %load_n %int_3\n" +
4098 "OpReturn\n" +
4099 "OpFunctionEnd",
4100 2, 0),
4101 // Test case 35: Don't fold n > 3 (signed)
4102 InstructionFoldingCase<uint32_t>(
4103 Header() + "%main = OpFunction %void None %void_func\n" +
4104 "%main_lab = OpLabel\n" +
4105 "%n = OpVariable %_ptr_int Function\n" +
4106 "%load_n = OpLoad %int %n\n" +
4107 "%2 = OpUGreaterThan %bool %load_n %int_3\n" +
4108 "OpReturn\n" +
4109 "OpFunctionEnd",
4110 2, 0),
4111 // Test case 36: Don't fold n <= 3 (signed)
4112 InstructionFoldingCase<uint32_t>(
4113 Header() + "%main = OpFunction %void None %void_func\n" +
4114 "%main_lab = OpLabel\n" +
4115 "%n = OpVariable %_ptr_int Function\n" +
4116 "%load_n = OpLoad %int %n\n" +
4117 "%2 = OpULessThanEqual %bool %load_n %int_3\n" +
4118 "OpReturn\n" +
4119 "OpFunctionEnd",
4120 2, 0),
4121 // Test case 37: Don't fold n >= 3 (signed)
4122 InstructionFoldingCase<uint32_t>(
4123 Header() + "%main = OpFunction %void None %void_func\n" +
4124 "%main_lab = OpLabel\n" +
4125 "%n = OpVariable %_ptr_int Function\n" +
4126 "%load_n = OpLoad %int %n\n" +
4127 "%2 = OpUGreaterThanEqual %bool %load_n %int_3\n" +
4128 "OpReturn\n" +
4129 "OpFunctionEnd",
4130 2, 0),
4131 // Test case 38: fold 1*n
4132 InstructionFoldingCase<uint32_t>(
4133 Header() + "%main = OpFunction %void None %void_func\n" +
4134 "%main_lab = OpLabel\n" +
4135 "%n = OpVariable %_ptr_int Function\n" +
4136 "%3 = OpLoad %int %n\n" +
4137 "%2 = OpIMul %int %int_1 %3\n" +
4138 "OpReturn\n" +
4139 "OpFunctionEnd",
4140 2, 3),
4141 // Test case 39: fold n*1
4142 InstructionFoldingCase<uint32_t>(
4143 Header() + "%main = OpFunction %void None %void_func\n" +
4144 "%main_lab = OpLabel\n" +
4145 "%n = OpVariable %_ptr_int Function\n" +
4146 "%3 = OpLoad %int %n\n" +
4147 "%2 = OpIMul %int %3 %int_1\n" +
4148 "OpReturn\n" +
4149 "OpFunctionEnd",
4150 2, 3),
4151 // Test case 40: Don't fold comparisons of 64-bit types
4152 // (https://github.com/KhronosGroup/SPIRV-Tools/issues/3343).
4153 InstructionFoldingCase<uint32_t>(
4154 Header() + "%main = OpFunction %void None %void_func\n" +
4155 "%main_lab = OpLabel\n" +
4156 "%2 = OpSLessThan %bool %long_0 %long_2\n" +
4157 "OpReturn\n" +
4158 "OpFunctionEnd",
4159 2, 0),
4160 // Test case 41: Don't fold OpSNegate for cooperative matrices.
4161 InstructionFoldingCase<uint32_t>(
4162 Header() + "%main = OpFunction %void None %void_func\n" +
4163 "%main_lab = OpLabel\n" +
4164 "%2 = OpSNegate %int_coop_matrix %undef_int_coop_matrix\n" +
4165 "OpReturn\n" +
4166 "OpFunctionEnd",
4167 2, 0),
4168 // Test case 42: Don't fold OpIAdd for cooperative matrices.
4169 InstructionFoldingCase<uint32_t>(
4170 Header() + "%main = OpFunction %void None %void_func\n" +
4171 "%main_lab = OpLabel\n" +
4172 "%2 = OpIAdd %int_coop_matrix %undef_int_coop_matrix %undef_int_coop_matrix\n" +
4173 "OpReturn\n" +
4174 "OpFunctionEnd",
4175 2, 0),
4176 // Test case 43: Don't fold OpISub for cooperative matrices.
4177 InstructionFoldingCase<uint32_t>(
4178 Header() + "%main = OpFunction %void None %void_func\n" +
4179 "%main_lab = OpLabel\n" +
4180 "%2 = OpISub %int_coop_matrix %undef_int_coop_matrix %undef_int_coop_matrix\n" +
4181 "OpReturn\n" +
4182 "OpFunctionEnd",
4183 2, 0),
4184 // Test case 44: Don't fold OpIMul for cooperative matrices.
4185 InstructionFoldingCase<uint32_t>(
4186 Header() + "%main = OpFunction %void None %void_func\n" +
4187 "%main_lab = OpLabel\n" +
4188 "%2 = OpIMul %int_coop_matrix %undef_int_coop_matrix %undef_int_coop_matrix\n" +
4189 "OpReturn\n" +
4190 "OpFunctionEnd",
4191 2, 0),
4192 // Test case 45: Don't fold OpSDiv for cooperative matrices.
4193 InstructionFoldingCase<uint32_t>(
4194 Header() + "%main = OpFunction %void None %void_func\n" +
4195 "%main_lab = OpLabel\n" +
4196 "%2 = OpSDiv %int_coop_matrix %undef_int_coop_matrix %undef_int_coop_matrix\n" +
4197 "OpReturn\n" +
4198 "OpFunctionEnd",
4199 2, 0),
4200 // Test case 46: Don't fold OpUDiv for cooperative matrices.
4201 InstructionFoldingCase<uint32_t>(
4202 Header() + "%main = OpFunction %void None %void_func\n" +
4203 "%main_lab = OpLabel\n" +
4204 "%2 = OpUDiv %uint_coop_matrix %undef_uint_coop_matrix %undef_uint_coop_matrix\n" +
4205 "OpReturn\n" +
4206 "OpFunctionEnd",
4207 2, 0),
4208 // Test case 47: Don't fold OpMatrixTimesScalar for cooperative matrices.
4209 InstructionFoldingCase<uint32_t>(
4210 Header() + "%main = OpFunction %void None %void_func\n" +
4211 "%main_lab = OpLabel\n" +
4212 "%2 = OpMatrixTimesScalar %uint_coop_matrix %undef_uint_coop_matrix %uint_3\n" +
4213 "OpReturn\n" +
4214 "OpFunctionEnd",
4215 2, 0)
4216 ));
4217
4218 INSTANTIATE_TEST_SUITE_P(CompositeExtractFoldingTest, GeneralInstructionFoldingTest,
4219 ::testing::Values(
4220 // Test case 0: fold Insert feeding extract
4221 InstructionFoldingCase<uint32_t>(
4222 Header() + "%main = OpFunction %void None %void_func\n" +
4223 "%main_lab = OpLabel\n" +
4224 "%n = OpVariable %_ptr_int Function\n" +
4225 "%2 = OpLoad %int %n\n" +
4226 "%3 = OpCompositeInsert %v4int %2 %v4int_0_0_0_0 0\n" +
4227 "%4 = OpCompositeInsert %v4int %int_1 %3 1\n" +
4228 "%5 = OpCompositeInsert %v4int %int_1 %4 2\n" +
4229 "%6 = OpCompositeInsert %v4int %int_1 %5 3\n" +
4230 "%7 = OpCompositeExtract %int %6 0\n" +
4231 "OpReturn\n" +
4232 "OpFunctionEnd",
4233 7, 2),
4234 // Test case 1: fold Composite construct feeding extract (position 0)
4235 InstructionFoldingCase<uint32_t>(
4236 Header() + "%main = OpFunction %void None %void_func\n" +
4237 "%main_lab = OpLabel\n" +
4238 "%n = OpVariable %_ptr_int Function\n" +
4239 "%2 = OpLoad %int %n\n" +
4240 "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %int_0\n" +
4241 "%4 = OpCompositeExtract %int %3 0\n" +
4242 "OpReturn\n" +
4243 "OpFunctionEnd",
4244 4, 2),
4245 // Test case 2: fold Composite construct feeding extract (position 3)
4246 InstructionFoldingCase<uint32_t>(
4247 Header() + "%main = OpFunction %void None %void_func\n" +
4248 "%main_lab = OpLabel\n" +
4249 "%n = OpVariable %_ptr_int Function\n" +
4250 "%2 = OpLoad %int %n\n" +
4251 "%3 = OpCompositeConstruct %v4int %2 %int_0 %int_0 %100\n" +
4252 "%4 = OpCompositeExtract %int %3 3\n" +
4253 "OpReturn\n" +
4254 "OpFunctionEnd",
4255 4, INT_0_ID),
4256 // Test case 3: fold Composite construct with vectors feeding extract (scalar element)
4257 InstructionFoldingCase<uint32_t>(
4258 Header() + "%main = OpFunction %void None %void_func\n" +
4259 "%main_lab = OpLabel\n" +
4260 "%n = OpVariable %_ptr_int Function\n" +
4261 "%2 = OpLoad %int %n\n" +
4262 "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
4263 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
4264 "%5 = OpCompositeExtract %int %4 3\n" +
4265 "OpReturn\n" +
4266 "OpFunctionEnd",
4267 5, INT_0_ID),
4268 // Test case 4: fold Composite construct with vectors feeding extract (start of vector element)
4269 InstructionFoldingCase<uint32_t>(
4270 Header() + "%main = OpFunction %void None %void_func\n" +
4271 "%main_lab = OpLabel\n" +
4272 "%n = OpVariable %_ptr_int Function\n" +
4273 "%2 = OpLoad %int %n\n" +
4274 "%3 = OpCompositeConstruct %v2int %2 %int_0\n" +
4275 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
4276 "%5 = OpCompositeExtract %int %4 0\n" +
4277 "OpReturn\n" +
4278 "OpFunctionEnd",
4279 5, 2),
4280 // Test case 5: fold Composite construct with vectors feeding extract (middle of vector element)
4281 InstructionFoldingCase<uint32_t>(
4282 Header() + "%main = OpFunction %void None %void_func\n" +
4283 "%main_lab = OpLabel\n" +
4284 "%n = OpVariable %_ptr_int Function\n" +
4285 "%2 = OpLoad %int %n\n" +
4286 "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
4287 "%4 = OpCompositeConstruct %v4int %3 %int_0 %100\n" +
4288 "%5 = OpCompositeExtract %int %4 1\n" +
4289 "OpReturn\n" +
4290 "OpFunctionEnd",
4291 5, 2),
4292 // Test case 6: fold Composite construct with multiple indices.
4293 InstructionFoldingCase<uint32_t>(
4294 Header() + "%main = OpFunction %void None %void_func\n" +
4295 "%main_lab = OpLabel\n" +
4296 "%n = OpVariable %_ptr_int Function\n" +
4297 "%2 = OpLoad %int %n\n" +
4298 "%3 = OpCompositeConstruct %v2int %int_0 %2\n" +
4299 "%4 = OpCompositeConstruct %struct_v2int_int_int %3 %int_0 %100\n" +
4300 "%5 = OpCompositeExtract %int %4 0 1\n" +
4301 "OpReturn\n" +
4302 "OpFunctionEnd",
4303 5, 2),
4304 // Test case 7: fold constant extract.
4305 InstructionFoldingCase<uint32_t>(
4306 Header() + "%main = OpFunction %void None %void_func\n" +
4307 "%main_lab = OpLabel\n" +
4308 "%2 = OpCompositeExtract %int %102 1\n" +
4309 "OpReturn\n" +
4310 "OpFunctionEnd",
4311 2, INT_7_ID),
4312 // Test case 8: constant struct has OpUndef
4313 InstructionFoldingCase<uint32_t>(
4314 Header() + "%main = OpFunction %void None %void_func\n" +
4315 "%main_lab = OpLabel\n" +
4316 "%2 = OpCompositeExtract %int %struct_undef_0_0 0 1\n" +
4317 "OpReturn\n" +
4318 "OpFunctionEnd",
4319 2, 0),
4320 // Test case 9: Extracting a member of element inserted via Insert
4321 InstructionFoldingCase<uint32_t>(
4322 Header() + "%main = OpFunction %void None %void_func\n" +
4323 "%main_lab = OpLabel\n" +
4324 "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
4325 "%2 = OpLoad %struct_v2int_int_int %n\n" +
4326 "%3 = OpCompositeInsert %struct_v2int_int_int %102 %2 0\n" +
4327 "%4 = OpCompositeExtract %int %3 0 1\n" +
4328 "OpReturn\n" +
4329 "OpFunctionEnd",
4330 4, 103),
4331 // Test case 10: Extracting a element that is partially changed by Insert. (Don't fold)
4332 InstructionFoldingCase<uint32_t>(
4333 Header() + "%main = OpFunction %void None %void_func\n" +
4334 "%main_lab = OpLabel\n" +
4335 "%n = OpVariable %_ptr_struct_v2int_int_int Function\n" +
4336 "%2 = OpLoad %struct_v2int_int_int %n\n" +
4337 "%3 = OpCompositeInsert %struct_v2int_int_int %int_0 %2 0 1\n" +
4338 "%4 = OpCompositeExtract %v2int %3 0\n" +
4339 "OpReturn\n" +
4340 "OpFunctionEnd",
4341 4, 0),
4342 // Test case 11: Extracting from result of vector shuffle (first input)
4343 InstructionFoldingCase<uint32_t>(
4344 Header() + "%main = OpFunction %void None %void_func\n" +
4345 "%main_lab = OpLabel\n" +
4346 "%n = OpVariable %_ptr_v2int Function\n" +
4347 "%2 = OpLoad %v2int %n\n" +
4348 "%3 = OpVectorShuffle %v2int %102 %2 3 0\n" +
4349 "%4 = OpCompositeExtract %int %3 1\n" +
4350 "OpReturn\n" +
4351 "OpFunctionEnd",
4352 4, INT_7_ID),
4353 // Test case 12: Extracting from result of vector shuffle (second input)
4354 InstructionFoldingCase<uint32_t>(
4355 Header() + "%main = OpFunction %void None %void_func\n" +
4356 "%main_lab = OpLabel\n" +
4357 "%n = OpVariable %_ptr_v2int Function\n" +
4358 "%2 = OpLoad %v2int %n\n" +
4359 "%3 = OpVectorShuffle %v2int %2 %102 2 0\n" +
4360 "%4 = OpCompositeExtract %int %3 0\n" +
4361 "OpReturn\n" +
4362 "OpFunctionEnd",
4363 4, INT_7_ID),
4364 // Test case 13: https://github.com/KhronosGroup/SPIRV-Tools/issues/2608
4365 // Out of bounds access. Do not fold.
4366 InstructionFoldingCase<uint32_t>(
4367 Header() + "%main = OpFunction %void None %void_func\n" +
4368 "%main_lab = OpLabel\n" +
4369 "%2 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1\n" +
4370 "%3 = OpCompositeExtract %float %2 4\n" +
4371 "OpReturn\n" +
4372 "OpFunctionEnd",
4373 3, 0),
4374 // Test case 14: https://github.com/KhronosGroup/SPIRV-Tools/issues/3631
4375 // Extract the component right after the vector constituent.
4376 InstructionFoldingCase<uint32_t>(
4377 Header() + "%main = OpFunction %void None %void_func\n" +
4378 "%main_lab = OpLabel\n" +
4379 "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
4380 "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
4381 "%4 = OpCompositeExtract %int %3 2\n" +
4382 "OpReturn\n" +
4383 "OpFunctionEnd",
4384 4, INT_0_ID),
4385 // Test case 15:
4386 // Don't fold extract fed by construct with vector result if the index is
4387 // past the last element.
4388 InstructionFoldingCase<uint32_t>(
4389 Header() + "%main = OpFunction %void None %void_func\n" +
4390 "%main_lab = OpLabel\n" +
4391 "%2 = OpCompositeConstruct %v2int %int_0 %int_0\n" +
4392 "%3 = OpCompositeConstruct %v4int %2 %100 %int_0\n" +
4393 "%4 = OpCompositeExtract %int %3 4\n" +
4394 "OpReturn\n" +
4395 "OpFunctionEnd",
4396 4, 0)
4397 ));
4398
4399 INSTANTIATE_TEST_SUITE_P(CompositeConstructFoldingTest, GeneralInstructionFoldingTest,
4400 ::testing::Values(
4401 // Test case 0: fold Extracts feeding construct
4402 InstructionFoldingCase<uint32_t>(
4403 Header() + "%main = OpFunction %void None %void_func\n" +
4404 "%main_lab = OpLabel\n" +
4405 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
4406 "%3 = OpCompositeExtract %int %2 0\n" +
4407 "%4 = OpCompositeExtract %int %2 1\n" +
4408 "%5 = OpCompositeExtract %int %2 2\n" +
4409 "%6 = OpCompositeExtract %int %2 3\n" +
4410 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
4411 "OpReturn\n" +
4412 "OpFunctionEnd",
4413 7, 2),
4414 // Test case 1: Don't fold Extracts feeding construct (Different source)
4415 InstructionFoldingCase<uint32_t>(
4416 Header() + "%main = OpFunction %void None %void_func\n" +
4417 "%main_lab = OpLabel\n" +
4418 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
4419 "%3 = OpCompositeExtract %int %2 0\n" +
4420 "%4 = OpCompositeExtract %int %2 1\n" +
4421 "%5 = OpCompositeExtract %int %2 2\n" +
4422 "%6 = OpCompositeExtract %int %v4int_0_0_0_0 3\n" +
4423 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
4424 "OpReturn\n" +
4425 "OpFunctionEnd",
4426 7, 0),
4427 // Test case 2: Don't fold Extracts feeding construct (bad indices)
4428 InstructionFoldingCase<uint32_t>(
4429 Header() + "%main = OpFunction %void None %void_func\n" +
4430 "%main_lab = OpLabel\n" +
4431 "%2 = OpCopyObject %v4int %v4int_0_0_0_0\n" +
4432 "%3 = OpCompositeExtract %int %2 0\n" +
4433 "%4 = OpCompositeExtract %int %2 0\n" +
4434 "%5 = OpCompositeExtract %int %2 2\n" +
4435 "%6 = OpCompositeExtract %int %2 3\n" +
4436 "%7 = OpCompositeConstruct %v4int %3 %4 %5 %6\n" +
4437 "OpReturn\n" +
4438 "OpFunctionEnd",
4439 7, 0),
4440 // Test case 3: Don't fold Extracts feeding construct (different type)
4441 InstructionFoldingCase<uint32_t>(
4442 Header() + "%main = OpFunction %void None %void_func\n" +
4443 "%main_lab = OpLabel\n" +
4444 "%2 = OpCopyObject %struct_v2int_int_int %struct_v2int_int_int_null\n" +
4445 "%3 = OpCompositeExtract %v2int %2 0\n" +
4446 "%4 = OpCompositeExtract %int %2 1\n" +
4447 "%5 = OpCompositeExtract %int %2 2\n" +
4448 "%7 = OpCompositeConstruct %v4int %3 %4 %5\n" +
4449 "OpReturn\n" +
4450 "OpFunctionEnd",
4451 7, 0),
4452 // Test case 4: Fold construct with constants to constant.
4453 InstructionFoldingCase<uint32_t>(
4454 Header() + "%main = OpFunction %void None %void_func\n" +
4455 "%main_lab = OpLabel\n" +
4456 "%2 = OpCompositeConstruct %v2int %103 %103\n" +
4457 "OpReturn\n" +
4458 "OpFunctionEnd",
4459 2, VEC2_0_ID),
4460 // Test case 5: Don't segfault when trying to fold an OpCompositeConstruct
4461 // for an empty struct, and we reached the id limit.
4462 InstructionFoldingCase<uint32_t>(
4463 Header() + "%empty_struct = OpTypeStruct\n" +
4464 "%main = OpFunction %void None %void_func\n" +
4465 "%main_lab = OpLabel\n" +
4466 "%4194303 = OpCompositeConstruct %empty_struct\n" +
4467 "OpReturn\n" +
4468 "OpFunctionEnd",
4469 4194303, 0)
4470 ));
4471
4472 INSTANTIATE_TEST_SUITE_P(PhiFoldingTest, GeneralInstructionFoldingTest,
4473 ::testing::Values(
4474 // Test case 0: Fold phi with the same values for all edges.
4475 InstructionFoldingCase<uint32_t>(
4476 Header() + "%main = OpFunction %void None %void_func\n" +
4477 "%main_lab = OpLabel\n" +
4478 " OpBranchConditional %true %l1 %l2\n" +
4479 "%l1 = OpLabel\n" +
4480 " OpBranch %merge_lab\n" +
4481 "%l2 = OpLabel\n" +
4482 " OpBranch %merge_lab\n" +
4483 "%merge_lab = OpLabel\n" +
4484 "%2 = OpPhi %int %100 %l1 %100 %l2\n" +
4485 "OpReturn\n" +
4486 "OpFunctionEnd",
4487 2, INT_0_ID),
4488 // Test case 1: Fold phi in pass through loop.
4489 InstructionFoldingCase<uint32_t>(
4490 Header() + "%main = OpFunction %void None %void_func\n" +
4491 "%main_lab = OpLabel\n" +
4492 " OpBranch %l1\n" +
4493 "%l1 = OpLabel\n" +
4494 "%2 = OpPhi %int %100 %main_lab %2 %l1\n" +
4495 " OpBranchConditional %true %l1 %merge_lab\n" +
4496 "%merge_lab = OpLabel\n" +
4497 "OpReturn\n" +
4498 "OpFunctionEnd",
4499 2, INT_0_ID),
4500 // Test case 2: Don't Fold phi because of different values.
4501 InstructionFoldingCase<uint32_t>(
4502 Header() + "%main = OpFunction %void None %void_func\n" +
4503 "%main_lab = OpLabel\n" +
4504 " OpBranch %l1\n" +
4505 "%l1 = OpLabel\n" +
4506 "%2 = OpPhi %int %int_0 %main_lab %int_3 %l1\n" +
4507 " OpBranchConditional %true %l1 %merge_lab\n" +
4508 "%merge_lab = OpLabel\n" +
4509 "OpReturn\n" +
4510 "OpFunctionEnd",
4511 2, 0)
4512 ));
4513
4514 INSTANTIATE_TEST_SUITE_P(FloatRedundantFoldingTest, GeneralInstructionFoldingTest,
4515 ::testing::Values(
4516 // Test case 0: Don't fold n + 1.0
4517 InstructionFoldingCase<uint32_t>(
4518 Header() + "%main = OpFunction %void None %void_func\n" +
4519 "%main_lab = OpLabel\n" +
4520 "%n = OpVariable %_ptr_float Function\n" +
4521 "%3 = OpLoad %float %n\n" +
4522 "%2 = OpFAdd %float %3 %float_2\n" +
4523 "OpReturn\n" +
4524 "OpFunctionEnd",
4525 2, 0),
4526 // Test case 1: Don't fold n - 1.0
4527 InstructionFoldingCase<uint32_t>(
4528 Header() + "%main = OpFunction %void None %void_func\n" +
4529 "%main_lab = OpLabel\n" +
4530 "%n = OpVariable %_ptr_float Function\n" +
4531 "%3 = OpLoad %float %n\n" +
4532 "%2 = OpFSub %float %3 %float_2\n" +
4533 "OpReturn\n" +
4534 "OpFunctionEnd",
4535 2, 0),
4536 // Test case 2: Don't fold n * 2.0
4537 InstructionFoldingCase<uint32_t>(
4538 Header() + "%main = OpFunction %void None %void_func\n" +
4539 "%main_lab = OpLabel\n" +
4540 "%n = OpVariable %_ptr_float Function\n" +
4541 "%3 = OpLoad %float %n\n" +
4542 "%2 = OpFMul %float %3 %float_2\n" +
4543 "OpReturn\n" +
4544 "OpFunctionEnd",
4545 2, 0),
4546 // Test case 3: Fold n + 0.0
4547 InstructionFoldingCase<uint32_t>(
4548 Header() + "%main = OpFunction %void None %void_func\n" +
4549 "%main_lab = OpLabel\n" +
4550 "%n = OpVariable %_ptr_float Function\n" +
4551 "%3 = OpLoad %float %n\n" +
4552 "%2 = OpFAdd %float %3 %float_0\n" +
4553 "OpReturn\n" +
4554 "OpFunctionEnd",
4555 2, 3),
4556 // Test case 4: Fold 0.0 + n
4557 InstructionFoldingCase<uint32_t>(
4558 Header() + "%main = OpFunction %void None %void_func\n" +
4559 "%main_lab = OpLabel\n" +
4560 "%n = OpVariable %_ptr_float Function\n" +
4561 "%3 = OpLoad %float %n\n" +
4562 "%2 = OpFAdd %float %float_0 %3\n" +
4563 "OpReturn\n" +
4564 "OpFunctionEnd",
4565 2, 3),
4566 // Test case 5: Fold n - 0.0
4567 InstructionFoldingCase<uint32_t>(
4568 Header() + "%main = OpFunction %void None %void_func\n" +
4569 "%main_lab = OpLabel\n" +
4570 "%n = OpVariable %_ptr_float Function\n" +
4571 "%3 = OpLoad %float %n\n" +
4572 "%2 = OpFSub %float %3 %float_0\n" +
4573 "OpReturn\n" +
4574 "OpFunctionEnd",
4575 2, 3),
4576 // Test case 6: Fold n * 1.0
4577 InstructionFoldingCase<uint32_t>(
4578 Header() + "%main = OpFunction %void None %void_func\n" +
4579 "%main_lab = OpLabel\n" +
4580 "%n = OpVariable %_ptr_float Function\n" +
4581 "%3 = OpLoad %float %n\n" +
4582 "%2 = OpFMul %float %3 %float_1\n" +
4583 "OpReturn\n" +
4584 "OpFunctionEnd",
4585 2, 3),
4586 // Test case 7: Fold 1.0 * n
4587 InstructionFoldingCase<uint32_t>(
4588 Header() + "%main = OpFunction %void None %void_func\n" +
4589 "%main_lab = OpLabel\n" +
4590 "%n = OpVariable %_ptr_float Function\n" +
4591 "%3 = OpLoad %float %n\n" +
4592 "%2 = OpFMul %float %float_1 %3\n" +
4593 "OpReturn\n" +
4594 "OpFunctionEnd",
4595 2, 3),
4596 // Test case 8: Fold n / 1.0
4597 InstructionFoldingCase<uint32_t>(
4598 Header() + "%main = OpFunction %void None %void_func\n" +
4599 "%main_lab = OpLabel\n" +
4600 "%n = OpVariable %_ptr_float Function\n" +
4601 "%3 = OpLoad %float %n\n" +
4602 "%2 = OpFDiv %float %3 %float_1\n" +
4603 "OpReturn\n" +
4604 "OpFunctionEnd",
4605 2, 3),
4606 // Test case 9: Fold n * 0.0
4607 InstructionFoldingCase<uint32_t>(
4608 Header() + "%main = OpFunction %void None %void_func\n" +
4609 "%main_lab = OpLabel\n" +
4610 "%n = OpVariable %_ptr_float Function\n" +
4611 "%3 = OpLoad %float %n\n" +
4612 "%2 = OpFMul %float %3 %104\n" +
4613 "OpReturn\n" +
4614 "OpFunctionEnd",
4615 2, FLOAT_0_ID),
4616 // Test case 10: Fold 0.0 * n
4617 InstructionFoldingCase<uint32_t>(
4618 Header() + "%main = OpFunction %void None %void_func\n" +
4619 "%main_lab = OpLabel\n" +
4620 "%n = OpVariable %_ptr_float Function\n" +
4621 "%3 = OpLoad %float %n\n" +
4622 "%2 = OpFMul %float %104 %3\n" +
4623 "OpReturn\n" +
4624 "OpFunctionEnd",
4625 2, FLOAT_0_ID),
4626 // Test case 11: Fold 0.0 / n
4627 InstructionFoldingCase<uint32_t>(
4628 Header() + "%main = OpFunction %void None %void_func\n" +
4629 "%main_lab = OpLabel\n" +
4630 "%n = OpVariable %_ptr_float Function\n" +
4631 "%3 = OpLoad %float %n\n" +
4632 "%2 = OpFDiv %float %104 %3\n" +
4633 "OpReturn\n" +
4634 "OpFunctionEnd",
4635 2, FLOAT_0_ID),
4636 // Test case 12: Don't fold mix(a, b, 2.0)
4637 InstructionFoldingCase<uint32_t>(
4638 Header() + "%main = OpFunction %void None %void_func\n" +
4639 "%main_lab = OpLabel\n" +
4640 "%a = OpVariable %_ptr_float Function\n" +
4641 "%b = OpVariable %_ptr_float Function\n" +
4642 "%3 = OpLoad %float %a\n" +
4643 "%4 = OpLoad %float %b\n" +
4644 "%2 = OpExtInst %float %1 FMix %3 %4 %float_2\n" +
4645 "OpReturn\n" +
4646 "OpFunctionEnd",
4647 2, 0),
4648 // Test case 13: Fold mix(a, b, 0.0)
4649 InstructionFoldingCase<uint32_t>(
4650 Header() + "%main = OpFunction %void None %void_func\n" +
4651 "%main_lab = OpLabel\n" +
4652 "%a = OpVariable %_ptr_float Function\n" +
4653 "%b = OpVariable %_ptr_float Function\n" +
4654 "%3 = OpLoad %float %a\n" +
4655 "%4 = OpLoad %float %b\n" +
4656 "%2 = OpExtInst %float %1 FMix %3 %4 %float_0\n" +
4657 "OpReturn\n" +
4658 "OpFunctionEnd",
4659 2, 3),
4660 // Test case 14: Fold mix(a, b, 1.0)
4661 InstructionFoldingCase<uint32_t>(
4662 Header() + "%main = OpFunction %void None %void_func\n" +
4663 "%main_lab = OpLabel\n" +
4664 "%a = OpVariable %_ptr_float Function\n" +
4665 "%b = OpVariable %_ptr_float Function\n" +
4666 "%3 = OpLoad %float %a\n" +
4667 "%4 = OpLoad %float %b\n" +
4668 "%2 = OpExtInst %float %1 FMix %3 %4 %float_1\n" +
4669 "OpReturn\n" +
4670 "OpFunctionEnd",
4671 2, 4),
4672 // Test case 15: Fold vector fadd with null
4673 InstructionFoldingCase<uint32_t>(
4674 Header() + "%main = OpFunction %void None %void_func\n" +
4675 "%main_lab = OpLabel\n" +
4676 "%a = OpVariable %_ptr_v2float Function\n" +
4677 "%2 = OpLoad %v2float %a\n" +
4678 "%3 = OpFAdd %v2float %2 %v2float_null\n" +
4679 "OpReturn\n" +
4680 "OpFunctionEnd",
4681 3, 2),
4682 // Test case 16: Fold vector fadd with null
4683 InstructionFoldingCase<uint32_t>(
4684 Header() + "%main = OpFunction %void None %void_func\n" +
4685 "%main_lab = OpLabel\n" +
4686 "%a = OpVariable %_ptr_v2float Function\n" +
4687 "%2 = OpLoad %v2float %a\n" +
4688 "%3 = OpFAdd %v2float %v2float_null %2\n" +
4689 "OpReturn\n" +
4690 "OpFunctionEnd",
4691 3, 2),
4692 // Test case 17: Fold vector fsub with null
4693 InstructionFoldingCase<uint32_t>(
4694 Header() + "%main = OpFunction %void None %void_func\n" +
4695 "%main_lab = OpLabel\n" +
4696 "%a = OpVariable %_ptr_v2float Function\n" +
4697 "%2 = OpLoad %v2float %a\n" +
4698 "%3 = OpFSub %v2float %2 %v2float_null\n" +
4699 "OpReturn\n" +
4700 "OpFunctionEnd",
4701 3, 2),
4702 // Test case 18: Fold 0.0(half) * n
4703 InstructionFoldingCase<uint32_t>(
4704 Header() + "%main = OpFunction %void None %void_func\n" +
4705 "%main_lab = OpLabel\n" +
4706 "%n = OpVariable %_ptr_half Function\n" +
4707 "%3 = OpLoad %half %n\n" +
4708 "%2 = OpFMul %half %108 %3\n" +
4709 "OpReturn\n" +
4710 "OpFunctionEnd",
4711 2, HALF_0_ID),
4712 // Test case 19: Don't fold 1.0(half) * n
4713 InstructionFoldingCase<uint32_t>(
4714 Header() + "%main = OpFunction %void None %void_func\n" +
4715 "%main_lab = OpLabel\n" +
4716 "%n = OpVariable %_ptr_half Function\n" +
4717 "%3 = OpLoad %half %n\n" +
4718 "%2 = OpFMul %half %half_1 %3\n" +
4719 "OpReturn\n" +
4720 "OpFunctionEnd",
4721 2, 0),
4722 // Test case 20: Don't fold 1.0 * 1.0 (half)
4723 InstructionFoldingCase<uint32_t>(
4724 Header() + "%main = OpFunction %void None %void_func\n" +
4725 "%main_lab = OpLabel\n" +
4726 "%2 = OpFMul %half %half_1 %half_1\n" +
4727 "OpReturn\n" +
4728 "OpFunctionEnd",
4729 2, 0),
4730 // Test case 21: Don't fold (0.0, 1.0) * (0.0, 1.0) (half)
4731 InstructionFoldingCase<uint32_t>(
4732 Header() + "%main = OpFunction %void None %void_func\n" +
4733 "%main_lab = OpLabel\n" +
4734 "%2 = OpFMul %v2half %half_0_1 %half_0_1\n" +
4735 "OpReturn\n" +
4736 "OpFunctionEnd",
4737 2, 0),
4738 // Test case 22: Don't fold (0.0, 1.0) dotp (0.0, 1.0) (half)
4739 InstructionFoldingCase<uint32_t>(
4740 Header() + "%main = OpFunction %void None %void_func\n" +
4741 "%main_lab = OpLabel\n" +
4742 "%2 = OpDot %half %half_0_1 %half_0_1\n" +
4743 "OpReturn\n" +
4744 "OpFunctionEnd",
4745 2, 0),
4746 // Test case 23: Don't fold 1.0(half) / 2.0(half)
4747 // We do not have to code to emulate 16-bit float operations. Just make sure we do not crash.
4748 InstructionFoldingCase<uint32_t>(
4749 Header() + "%main = OpFunction %void None %void_func\n" +
4750 "%main_lab = OpLabel\n" +
4751 "%n = OpVariable %_ptr_half Function\n" +
4752 "%3 = OpLoad %half %n\n" +
4753 "%2 = OpFDiv %half %half_1 %half_2\n" +
4754 "OpReturn\n" +
4755 "OpFunctionEnd",
4756 2, 0),
4757 // Test case 24: Don't fold OpFNegate for cooperative matrices.
4758 InstructionFoldingCase<uint32_t>(
4759 Header() + "%main = OpFunction %void None %void_func\n" +
4760 "%main_lab = OpLabel\n" +
4761 "%2 = OpFNegate %float_coop_matrix %undef_float_coop_matrix\n" +
4762 "OpReturn\n" +
4763 "OpFunctionEnd",
4764 2, 0),
4765 // Test case 25: Don't fold OpIAdd for cooperative matrices.
4766 InstructionFoldingCase<uint32_t>(
4767 Header() + "%main = OpFunction %void None %void_func\n" +
4768 "%main_lab = OpLabel\n" +
4769 "%2 = OpFAdd %float_coop_matrix %undef_float_coop_matrix %undef_float_coop_matrix\n" +
4770 "OpReturn\n" +
4771 "OpFunctionEnd",
4772 2, 0),
4773 // Test case 26: Don't fold OpISub for cooperative matrices.
4774 InstructionFoldingCase<uint32_t>(
4775 Header() + "%main = OpFunction %void None %void_func\n" +
4776 "%main_lab = OpLabel\n" +
4777 "%2 = OpFSub %float_coop_matrix %undef_float_coop_matrix %undef_float_coop_matrix\n" +
4778 "OpReturn\n" +
4779 "OpFunctionEnd",
4780 2, 0),
4781 // Test case 27: Don't fold OpIMul for cooperative matrices.
4782 InstructionFoldingCase<uint32_t>(
4783 Header() + "%main = OpFunction %void None %void_func\n" +
4784 "%main_lab = OpLabel\n" +
4785 "%2 = OpFMul %float_coop_matrix %undef_float_coop_matrix %undef_float_coop_matrix\n" +
4786 "OpReturn\n" +
4787 "OpFunctionEnd",
4788 2, 0),
4789 // Test case 28: Don't fold OpSDiv for cooperative matrices.
4790 InstructionFoldingCase<uint32_t>(
4791 Header() + "%main = OpFunction %void None %void_func\n" +
4792 "%main_lab = OpLabel\n" +
4793 "%2 = OpFDiv %float_coop_matrix %undef_float_coop_matrix %undef_float_coop_matrix\n" +
4794 "OpReturn\n" +
4795 "OpFunctionEnd",
4796 2, 0),
4797 // Test case 29: Don't fold OpMatrixTimesScalar for cooperative matrices.
4798 InstructionFoldingCase<uint32_t>(
4799 Header() + "%main = OpFunction %void None %void_func\n" +
4800 "%main_lab = OpLabel\n" +
4801 "%2 = OpMatrixTimesScalar %float_coop_matrix %undef_float_coop_matrix %float_3\n" +
4802 "OpReturn\n" +
4803 "OpFunctionEnd",
4804 2, 0)
4805 ));
4806
4807 INSTANTIATE_TEST_SUITE_P(DoubleRedundantFoldingTest, GeneralInstructionFoldingTest,
4808 ::testing::Values(
4809 // Test case 0: Don't fold n + 1.0
4810 InstructionFoldingCase<uint32_t>(
4811 Header() + "%main = OpFunction %void None %void_func\n" +
4812 "%main_lab = OpLabel\n" +
4813 "%n = OpVariable %_ptr_double Function\n" +
4814 "%3 = OpLoad %double %n\n" +
4815 "%2 = OpFAdd %double %3 %double_2\n" +
4816 "OpReturn\n" +
4817 "OpFunctionEnd",
4818 2, 0),
4819 // Test case 1: Don't fold n - 1.0
4820 InstructionFoldingCase<uint32_t>(
4821 Header() + "%main = OpFunction %void None %void_func\n" +
4822 "%main_lab = OpLabel\n" +
4823 "%n = OpVariable %_ptr_double Function\n" +
4824 "%3 = OpLoad %double %n\n" +
4825 "%2 = OpFSub %double %3 %double_2\n" +
4826 "OpReturn\n" +
4827 "OpFunctionEnd",
4828 2, 0),
4829 // Test case 2: Don't fold n * 2.0
4830 InstructionFoldingCase<uint32_t>(
4831 Header() + "%main = OpFunction %void None %void_func\n" +
4832 "%main_lab = OpLabel\n" +
4833 "%n = OpVariable %_ptr_double Function\n" +
4834 "%3 = OpLoad %double %n\n" +
4835 "%2 = OpFMul %double %3 %double_2\n" +
4836 "OpReturn\n" +
4837 "OpFunctionEnd",
4838 2, 0),
4839 // Test case 3: Fold n + 0.0
4840 InstructionFoldingCase<uint32_t>(
4841 Header() + "%main = OpFunction %void None %void_func\n" +
4842 "%main_lab = OpLabel\n" +
4843 "%n = OpVariable %_ptr_double Function\n" +
4844 "%3 = OpLoad %double %n\n" +
4845 "%2 = OpFAdd %double %3 %double_0\n" +
4846 "OpReturn\n" +
4847 "OpFunctionEnd",
4848 2, 3),
4849 // Test case 4: Fold 0.0 + n
4850 InstructionFoldingCase<uint32_t>(
4851 Header() + "%main = OpFunction %void None %void_func\n" +
4852 "%main_lab = OpLabel\n" +
4853 "%n = OpVariable %_ptr_double Function\n" +
4854 "%3 = OpLoad %double %n\n" +
4855 "%2 = OpFAdd %double %double_0 %3\n" +
4856 "OpReturn\n" +
4857 "OpFunctionEnd",
4858 2, 3),
4859 // Test case 5: Fold n - 0.0
4860 InstructionFoldingCase<uint32_t>(
4861 Header() + "%main = OpFunction %void None %void_func\n" +
4862 "%main_lab = OpLabel\n" +
4863 "%n = OpVariable %_ptr_double Function\n" +
4864 "%3 = OpLoad %double %n\n" +
4865 "%2 = OpFSub %double %3 %double_0\n" +
4866 "OpReturn\n" +
4867 "OpFunctionEnd",
4868 2, 3),
4869 // Test case 6: Fold n * 1.0
4870 InstructionFoldingCase<uint32_t>(
4871 Header() + "%main = OpFunction %void None %void_func\n" +
4872 "%main_lab = OpLabel\n" +
4873 "%n = OpVariable %_ptr_double Function\n" +
4874 "%3 = OpLoad %double %n\n" +
4875 "%2 = OpFMul %double %3 %double_1\n" +
4876 "OpReturn\n" +
4877 "OpFunctionEnd",
4878 2, 3),
4879 // Test case 7: Fold 1.0 * n
4880 InstructionFoldingCase<uint32_t>(
4881 Header() + "%main = OpFunction %void None %void_func\n" +
4882 "%main_lab = OpLabel\n" +
4883 "%n = OpVariable %_ptr_double Function\n" +
4884 "%3 = OpLoad %double %n\n" +
4885 "%2 = OpFMul %double %double_1 %3\n" +
4886 "OpReturn\n" +
4887 "OpFunctionEnd",
4888 2, 3),
4889 // Test case 8: Fold n / 1.0
4890 InstructionFoldingCase<uint32_t>(
4891 Header() + "%main = OpFunction %void None %void_func\n" +
4892 "%main_lab = OpLabel\n" +
4893 "%n = OpVariable %_ptr_double Function\n" +
4894 "%3 = OpLoad %double %n\n" +
4895 "%2 = OpFDiv %double %3 %double_1\n" +
4896 "OpReturn\n" +
4897 "OpFunctionEnd",
4898 2, 3),
4899 // Test case 9: Fold n * 0.0
4900 InstructionFoldingCase<uint32_t>(
4901 Header() + "%main = OpFunction %void None %void_func\n" +
4902 "%main_lab = OpLabel\n" +
4903 "%n = OpVariable %_ptr_double Function\n" +
4904 "%3 = OpLoad %double %n\n" +
4905 "%2 = OpFMul %double %3 %105\n" +
4906 "OpReturn\n" +
4907 "OpFunctionEnd",
4908 2, DOUBLE_0_ID),
4909 // Test case 10: Fold 0.0 * n
4910 InstructionFoldingCase<uint32_t>(
4911 Header() + "%main = OpFunction %void None %void_func\n" +
4912 "%main_lab = OpLabel\n" +
4913 "%n = OpVariable %_ptr_double Function\n" +
4914 "%3 = OpLoad %double %n\n" +
4915 "%2 = OpFMul %double %105 %3\n" +
4916 "OpReturn\n" +
4917 "OpFunctionEnd",
4918 2, DOUBLE_0_ID),
4919 // Test case 11: Fold 0.0 / n
4920 InstructionFoldingCase<uint32_t>(
4921 Header() + "%main = OpFunction %void None %void_func\n" +
4922 "%main_lab = OpLabel\n" +
4923 "%n = OpVariable %_ptr_double Function\n" +
4924 "%3 = OpLoad %double %n\n" +
4925 "%2 = OpFDiv %double %105 %3\n" +
4926 "OpReturn\n" +
4927 "OpFunctionEnd",
4928 2, DOUBLE_0_ID),
4929 // Test case 12: Don't fold mix(a, b, 2.0)
4930 InstructionFoldingCase<uint32_t>(
4931 Header() + "%main = OpFunction %void None %void_func\n" +
4932 "%main_lab = OpLabel\n" +
4933 "%a = OpVariable %_ptr_double Function\n" +
4934 "%b = OpVariable %_ptr_double Function\n" +
4935 "%3 = OpLoad %double %a\n" +
4936 "%4 = OpLoad %double %b\n" +
4937 "%2 = OpExtInst %double %1 FMix %3 %4 %double_2\n" +
4938 "OpReturn\n" +
4939 "OpFunctionEnd",
4940 2, 0),
4941 // Test case 13: Fold mix(a, b, 0.0)
4942 InstructionFoldingCase<uint32_t>(
4943 Header() + "%main = OpFunction %void None %void_func\n" +
4944 "%main_lab = OpLabel\n" +
4945 "%a = OpVariable %_ptr_double Function\n" +
4946 "%b = OpVariable %_ptr_double Function\n" +
4947 "%3 = OpLoad %double %a\n" +
4948 "%4 = OpLoad %double %b\n" +
4949 "%2 = OpExtInst %double %1 FMix %3 %4 %double_0\n" +
4950 "OpReturn\n" +
4951 "OpFunctionEnd",
4952 2, 3),
4953 // Test case 14: Fold mix(a, b, 1.0)
4954 InstructionFoldingCase<uint32_t>(
4955 Header() + "%main = OpFunction %void None %void_func\n" +
4956 "%main_lab = OpLabel\n" +
4957 "%a = OpVariable %_ptr_double Function\n" +
4958 "%b = OpVariable %_ptr_double Function\n" +
4959 "%3 = OpLoad %double %a\n" +
4960 "%4 = OpLoad %double %b\n" +
4961 "%2 = OpExtInst %double %1 FMix %3 %4 %double_1\n" +
4962 "OpReturn\n" +
4963 "OpFunctionEnd",
4964 2, 4)
4965 ));
4966
4967 INSTANTIATE_TEST_SUITE_P(FloatVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
4968 ::testing::Values(
4969 // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
4970 InstructionFoldingCase<uint32_t>(
4971 Header() + "%main = OpFunction %void None %void_func\n" +
4972 "%main_lab = OpLabel\n" +
4973 "%n = OpVariable %_ptr_v4float Function\n" +
4974 "%3 = OpLoad %v4float %n\n" +
4975 "%2 = OpFMul %v4float %3 %v4float_0_0_0_1\n" +
4976 "OpReturn\n" +
4977 "OpFunctionEnd",
4978 2, 0),
4979 // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
4980 InstructionFoldingCase<uint32_t>(
4981 Header() + "%main = OpFunction %void None %void_func\n" +
4982 "%main_lab = OpLabel\n" +
4983 "%n = OpVariable %_ptr_v4float Function\n" +
4984 "%3 = OpLoad %v4float %n\n" +
4985 "%2 = OpFMul %v4float %3 %106\n" +
4986 "OpReturn\n" +
4987 "OpFunctionEnd",
4988 2, VEC4_0_ID),
4989 // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
4990 InstructionFoldingCase<uint32_t>(
4991 Header() + "%main = OpFunction %void None %void_func\n" +
4992 "%main_lab = OpLabel\n" +
4993 "%n = OpVariable %_ptr_v4float Function\n" +
4994 "%3 = OpLoad %v4float %n\n" +
4995 "%2 = OpFMul %v4float %3 %v4float_1_1_1_1\n" +
4996 "OpReturn\n" +
4997 "OpFunctionEnd",
4998 2, 3)
4999 ));
5000
5001 INSTANTIATE_TEST_SUITE_P(DoubleVectorRedundantFoldingTest, GeneralInstructionFoldingTest,
5002 ::testing::Values(
5003 // Test case 0: Don't fold a * vec4(0.0, 0.0, 0.0, 1.0)
5004 InstructionFoldingCase<uint32_t>(
5005 Header() + "%main = OpFunction %void None %void_func\n" +
5006 "%main_lab = OpLabel\n" +
5007 "%n = OpVariable %_ptr_v4double Function\n" +
5008 "%3 = OpLoad %v4double %n\n" +
5009 "%2 = OpFMul %v4double %3 %v4double_0_0_0_1\n" +
5010 "OpReturn\n" +
5011 "OpFunctionEnd",
5012 2, 0),
5013 // Test case 1: Fold a * vec4(0.0, 0.0, 0.0, 0.0)
5014 InstructionFoldingCase<uint32_t>(
5015 Header() + "%main = OpFunction %void None %void_func\n" +
5016 "%main_lab = OpLabel\n" +
5017 "%n = OpVariable %_ptr_v4double Function\n" +
5018 "%3 = OpLoad %v4double %n\n" +
5019 "%2 = OpFMul %v4double %3 %106\n" +
5020 "OpReturn\n" +
5021 "OpFunctionEnd",
5022 2, DVEC4_0_ID),
5023 // Test case 2: Fold a * vec4(1.0, 1.0, 1.0, 1.0)
5024 InstructionFoldingCase<uint32_t>(
5025 Header() + "%main = OpFunction %void None %void_func\n" +
5026 "%main_lab = OpLabel\n" +
5027 "%n = OpVariable %_ptr_v4double Function\n" +
5028 "%3 = OpLoad %v4double %n\n" +
5029 "%2 = OpFMul %v4double %3 %v4double_1_1_1_1\n" +
5030 "OpReturn\n" +
5031 "OpFunctionEnd",
5032 2, 3)
5033 ));
5034
5035 INSTANTIATE_TEST_SUITE_P(IntegerRedundantFoldingTest, GeneralInstructionFoldingTest,
5036 ::testing::Values(
5037 // Test case 0: Don't fold n + 1
5038 InstructionFoldingCase<uint32_t>(
5039 Header() + "%main = OpFunction %void None %void_func\n" +
5040 "%main_lab = OpLabel\n" +
5041 "%n = OpVariable %_ptr_uint Function\n" +
5042 "%3 = OpLoad %uint %n\n" +
5043 "%2 = OpIAdd %uint %3 %uint_1\n" +
5044 "OpReturn\n" +
5045 "OpFunctionEnd",
5046 2, 0),
5047 // Test case 1: Don't fold 1 + n
5048 InstructionFoldingCase<uint32_t>(
5049 Header() + "%main = OpFunction %void None %void_func\n" +
5050 "%main_lab = OpLabel\n" +
5051 "%n = OpVariable %_ptr_uint Function\n" +
5052 "%3 = OpLoad %uint %n\n" +
5053 "%2 = OpIAdd %uint %uint_1 %3\n" +
5054 "OpReturn\n" +
5055 "OpFunctionEnd",
5056 2, 0),
5057 // Test case 2: Fold n + 0
5058 InstructionFoldingCase<uint32_t>(
5059 Header() + "%main = OpFunction %void None %void_func\n" +
5060 "%main_lab = OpLabel\n" +
5061 "%n = OpVariable %_ptr_uint Function\n" +
5062 "%3 = OpLoad %uint %n\n" +
5063 "%2 = OpIAdd %uint %3 %uint_0\n" +
5064 "OpReturn\n" +
5065 "OpFunctionEnd",
5066 2, 3),
5067 // Test case 3: Fold 0 + n
5068 InstructionFoldingCase<uint32_t>(
5069 Header() + "%main = OpFunction %void None %void_func\n" +
5070 "%main_lab = OpLabel\n" +
5071 "%n = OpVariable %_ptr_uint Function\n" +
5072 "%3 = OpLoad %uint %n\n" +
5073 "%2 = OpIAdd %uint %uint_0 %3\n" +
5074 "OpReturn\n" +
5075 "OpFunctionEnd",
5076 2, 3),
5077 // Test case 4: Don't fold n + (1,0)
5078 InstructionFoldingCase<uint32_t>(
5079 Header() + "%main = OpFunction %void None %void_func\n" +
5080 "%main_lab = OpLabel\n" +
5081 "%n = OpVariable %_ptr_v2int Function\n" +
5082 "%3 = OpLoad %v2int %n\n" +
5083 "%2 = OpIAdd %v2int %3 %v2int_1_0\n" +
5084 "OpReturn\n" +
5085 "OpFunctionEnd",
5086 2, 0),
5087 // Test case 5: Don't fold (1,0) + n
5088 InstructionFoldingCase<uint32_t>(
5089 Header() + "%main = OpFunction %void None %void_func\n" +
5090 "%main_lab = OpLabel\n" +
5091 "%n = OpVariable %_ptr_v2int Function\n" +
5092 "%3 = OpLoad %v2int %n\n" +
5093 "%2 = OpIAdd %v2int %v2int_1_0 %3\n" +
5094 "OpReturn\n" +
5095 "OpFunctionEnd",
5096 2, 0),
5097 // Test case 6: Fold n + (0,0)
5098 InstructionFoldingCase<uint32_t>(
5099 Header() + "%main = OpFunction %void None %void_func\n" +
5100 "%main_lab = OpLabel\n" +
5101 "%n = OpVariable %_ptr_v2int Function\n" +
5102 "%3 = OpLoad %v2int %n\n" +
5103 "%2 = OpIAdd %v2int %3 %v2int_0_0\n" +
5104 "OpReturn\n" +
5105 "OpFunctionEnd",
5106 2, 3),
5107 // Test case 7: Fold (0,0) + n
5108 InstructionFoldingCase<uint32_t>(
5109 Header() + "%main = OpFunction %void None %void_func\n" +
5110 "%main_lab = OpLabel\n" +
5111 "%n = OpVariable %_ptr_v2int Function\n" +
5112 "%3 = OpLoad %v2int %n\n" +
5113 "%2 = OpIAdd %v2int %v2int_0_0 %3\n" +
5114 "OpReturn\n" +
5115 "OpFunctionEnd",
5116 2, 3),
5117 // Test case 8: Don't fold because of undefined value. Using 4294967295
5118 // means that entry is undefined. We do not expect it to ever happen, so
5119 // not worth folding.
5120 InstructionFoldingCase<uint32_t>(
5121 Header() + "%main = OpFunction %void None %void_func\n" +
5122 "%main_lab = OpLabel\n" +
5123 "%n = OpVariable %_ptr_int Function\n" +
5124 "%load = OpLoad %int %n\n" +
5125 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 4294967295 3\n" +
5126 "OpReturn\n" +
5127 "OpFunctionEnd",
5128 2, 0),
5129 // Test case 9: Don't fold because of undefined value. Using 4294967295
5130 // means that entry is undefined. We do not expect it to ever happen, so
5131 // not worth folding.
5132 InstructionFoldingCase<uint32_t>(
5133 Header() + "%main = OpFunction %void None %void_func\n" +
5134 "%main_lab = OpLabel\n" +
5135 "%n = OpVariable %_ptr_int Function\n" +
5136 "%load = OpLoad %int %n\n" +
5137 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 4294967295 \n" +
5138 "OpReturn\n" +
5139 "OpFunctionEnd",
5140 2, 0)
5141 ));
5142
5143 INSTANTIATE_TEST_SUITE_P(ClampAndCmpLHS, GeneralInstructionFoldingTest,
5144 ::testing::Values(
5145 // Test case 0: Don't Fold 0.0 < clamp(-1, 1)
5146 InstructionFoldingCase<uint32_t>(
5147 Header() + "%main = OpFunction %void None %void_func\n" +
5148 "%main_lab = OpLabel\n" +
5149 "%n = OpVariable %_ptr_float Function\n" +
5150 "%ld = OpLoad %float %n\n" +
5151 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5152 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
5153 "OpReturn\n" +
5154 "OpFunctionEnd",
5155 2, 0),
5156 // Test case 1: Don't Fold 0.0 < clamp(-1, 1)
5157 InstructionFoldingCase<uint32_t>(
5158 Header() + "%main = OpFunction %void None %void_func\n" +
5159 "%main_lab = OpLabel\n" +
5160 "%n = OpVariable %_ptr_float Function\n" +
5161 "%ld = OpLoad %float %n\n" +
5162 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5163 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
5164 "OpReturn\n" +
5165 "OpFunctionEnd",
5166 2, 0),
5167 // Test case 2: Don't Fold 0.0 <= clamp(-1, 1)
5168 InstructionFoldingCase<uint32_t>(
5169 Header() + "%main = OpFunction %void None %void_func\n" +
5170 "%main_lab = OpLabel\n" +
5171 "%n = OpVariable %_ptr_float Function\n" +
5172 "%ld = OpLoad %float %n\n" +
5173 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5174 "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" +
5175 "OpReturn\n" +
5176 "OpFunctionEnd",
5177 2, 0),
5178 // Test case 3: Don't Fold 0.0 <= clamp(-1, 1)
5179 InstructionFoldingCase<uint32_t>(
5180 Header() + "%main = OpFunction %void None %void_func\n" +
5181 "%main_lab = OpLabel\n" +
5182 "%n = OpVariable %_ptr_float Function\n" +
5183 "%ld = OpLoad %float %n\n" +
5184 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5185 "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" +
5186 "OpReturn\n" +
5187 "OpFunctionEnd",
5188 2, 0),
5189 // Test case 4: Don't Fold 0.0 > clamp(-1, 1)
5190 InstructionFoldingCase<uint32_t>(
5191 Header() + "%main = OpFunction %void None %void_func\n" +
5192 "%main_lab = OpLabel\n" +
5193 "%n = OpVariable %_ptr_float Function\n" +
5194 "%ld = OpLoad %float %n\n" +
5195 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5196 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
5197 "OpReturn\n" +
5198 "OpFunctionEnd",
5199 2, 0),
5200 // Test case 5: Don't Fold 0.0 > clamp(-1, 1)
5201 InstructionFoldingCase<uint32_t>(
5202 Header() + "%main = OpFunction %void None %void_func\n" +
5203 "%main_lab = OpLabel\n" +
5204 "%n = OpVariable %_ptr_float Function\n" +
5205 "%ld = OpLoad %float %n\n" +
5206 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5207 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
5208 "OpReturn\n" +
5209 "OpFunctionEnd",
5210 2, 0),
5211 // Test case 6: Don't Fold 0.0 >= clamp(-1, 1)
5212 InstructionFoldingCase<uint32_t>(
5213 Header() + "%main = OpFunction %void None %void_func\n" +
5214 "%main_lab = OpLabel\n" +
5215 "%n = OpVariable %_ptr_float Function\n" +
5216 "%ld = OpLoad %float %n\n" +
5217 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5218 "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" +
5219 "OpReturn\n" +
5220 "OpFunctionEnd",
5221 2, 0),
5222 // Test case 7: Don't Fold 0.0 >= clamp(-1, 1)
5223 InstructionFoldingCase<uint32_t>(
5224 Header() + "%main = OpFunction %void None %void_func\n" +
5225 "%main_lab = OpLabel\n" +
5226 "%n = OpVariable %_ptr_float Function\n" +
5227 "%ld = OpLoad %float %n\n" +
5228 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5229 "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" +
5230 "OpReturn\n" +
5231 "OpFunctionEnd",
5232 2, 0),
5233 // Test case 8: Don't Fold 0.0 < clamp(0, 1)
5234 InstructionFoldingCase<uint32_t>(
5235 Header() + "%main = OpFunction %void None %void_func\n" +
5236 "%main_lab = OpLabel\n" +
5237 "%n = OpVariable %_ptr_float Function\n" +
5238 "%ld = OpLoad %float %n\n" +
5239 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
5240 "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" +
5241 "OpReturn\n" +
5242 "OpFunctionEnd",
5243 2, 0),
5244 // Test case 9: Don't Fold 0.0 < clamp(0, 1)
5245 InstructionFoldingCase<uint32_t>(
5246 Header() + "%main = OpFunction %void None %void_func\n" +
5247 "%main_lab = OpLabel\n" +
5248 "%n = OpVariable %_ptr_float Function\n" +
5249 "%ld = OpLoad %float %n\n" +
5250 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
5251 "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" +
5252 "OpReturn\n" +
5253 "OpFunctionEnd",
5254 2, 0),
5255 // Test case 10: Don't Fold 0.0 > clamp(-1, 0)
5256 InstructionFoldingCase<uint32_t>(
5257 Header() + "%main = OpFunction %void None %void_func\n" +
5258 "%main_lab = OpLabel\n" +
5259 "%n = OpVariable %_ptr_float Function\n" +
5260 "%ld = OpLoad %float %n\n" +
5261 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5262 "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" +
5263 "OpReturn\n" +
5264 "OpFunctionEnd",
5265 2, 0),
5266 // Test case 11: Don't Fold 0.0 > clamp(-1, 0)
5267 InstructionFoldingCase<uint32_t>(
5268 Header() + "%main = OpFunction %void None %void_func\n" +
5269 "%main_lab = OpLabel\n" +
5270 "%n = OpVariable %_ptr_float Function\n" +
5271 "%ld = OpLoad %float %n\n" +
5272 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5273 "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" +
5274 "OpReturn\n" +
5275 "OpFunctionEnd",
5276 2, 0)
5277 ));
5278
5279 INSTANTIATE_TEST_SUITE_P(ClampAndCmpRHS, GeneralInstructionFoldingTest,
5280 ::testing::Values(
5281 // Test case 0: Don't Fold clamp(-1, 1) < 0.0
5282 InstructionFoldingCase<uint32_t>(
5283 Header() + "%main = OpFunction %void None %void_func\n" +
5284 "%main_lab = OpLabel\n" +
5285 "%n = OpVariable %_ptr_float Function\n" +
5286 "%ld = OpLoad %float %n\n" +
5287 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5288 "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
5289 "OpReturn\n" +
5290 "OpFunctionEnd",
5291 2, 0),
5292 // Test case 1: Don't Fold clamp(-1, 1) < 0.0
5293 InstructionFoldingCase<uint32_t>(
5294 Header() + "%main = OpFunction %void None %void_func\n" +
5295 "%main_lab = OpLabel\n" +
5296 "%n = OpVariable %_ptr_float Function\n" +
5297 "%ld = OpLoad %float %n\n" +
5298 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5299 "%2 = OpFOrdLessThan %bool %clamp %float_0\n" +
5300 "OpReturn\n" +
5301 "OpFunctionEnd",
5302 2, 0),
5303 // Test case 2: Don't Fold clamp(-1, 1) <= 0.0
5304 InstructionFoldingCase<uint32_t>(
5305 Header() + "%main = OpFunction %void None %void_func\n" +
5306 "%main_lab = OpLabel\n" +
5307 "%n = OpVariable %_ptr_float Function\n" +
5308 "%ld = OpLoad %float %n\n" +
5309 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5310 "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" +
5311 "OpReturn\n" +
5312 "OpFunctionEnd",
5313 2, 0),
5314 // Test case 3: Don't Fold clamp(-1, 1) <= 0.0
5315 InstructionFoldingCase<uint32_t>(
5316 Header() + "%main = OpFunction %void None %void_func\n" +
5317 "%main_lab = OpLabel\n" +
5318 "%n = OpVariable %_ptr_float Function\n" +
5319 "%ld = OpLoad %float %n\n" +
5320 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5321 "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" +
5322 "OpReturn\n" +
5323 "OpFunctionEnd",
5324 2, 0),
5325 // Test case 4: Don't Fold clamp(-1, 1) > 0.0
5326 InstructionFoldingCase<uint32_t>(
5327 Header() + "%main = OpFunction %void None %void_func\n" +
5328 "%main_lab = OpLabel\n" +
5329 "%n = OpVariable %_ptr_float Function\n" +
5330 "%ld = OpLoad %float %n\n" +
5331 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5332 "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" +
5333 "OpReturn\n" +
5334 "OpFunctionEnd",
5335 2, 0),
5336 // Test case 5: Don't Fold clamp(-1, 1) > 0.0
5337 InstructionFoldingCase<uint32_t>(
5338 Header() + "%main = OpFunction %void None %void_func\n" +
5339 "%main_lab = OpLabel\n" +
5340 "%n = OpVariable %_ptr_float Function\n" +
5341 "%ld = OpLoad %float %n\n" +
5342 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5343 "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" +
5344 "OpReturn\n" +
5345 "OpFunctionEnd",
5346 2, 0),
5347 // Test case 6: Don't Fold clamp(-1, 1) >= 0.0
5348 InstructionFoldingCase<uint32_t>(
5349 Header() + "%main = OpFunction %void None %void_func\n" +
5350 "%main_lab = OpLabel\n" +
5351 "%n = OpVariable %_ptr_float Function\n" +
5352 "%ld = OpLoad %float %n\n" +
5353 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5354 "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_0\n" +
5355 "OpReturn\n" +
5356 "OpFunctionEnd",
5357 2, 0),
5358 // Test case 7: Don't Fold clamp(-1, 1) >= 0.0
5359 InstructionFoldingCase<uint32_t>(
5360 Header() + "%main = OpFunction %void None %void_func\n" +
5361 "%main_lab = OpLabel\n" +
5362 "%n = OpVariable %_ptr_float Function\n" +
5363 "%ld = OpLoad %float %n\n" +
5364 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_1\n" +
5365 "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" +
5366 "OpReturn\n" +
5367 "OpFunctionEnd",
5368 2, 0),
5369 // Test case 8: Don't Fold clamp(-1, 0) < 0.0
5370 InstructionFoldingCase<uint32_t>(
5371 Header() + "%main = OpFunction %void None %void_func\n" +
5372 "%main_lab = OpLabel\n" +
5373 "%n = OpVariable %_ptr_float Function\n" +
5374 "%ld = OpLoad %float %n\n" +
5375 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5376 "%2 = OpFUnordLessThan %bool %clamp %float_0\n" +
5377 "OpReturn\n" +
5378 "OpFunctionEnd",
5379 2, 0),
5380 // Test case 9: Don't Fold clamp(0, 1) < 1
5381 InstructionFoldingCase<uint32_t>(
5382 Header() + "%main = OpFunction %void None %void_func\n" +
5383 "%main_lab = OpLabel\n" +
5384 "%n = OpVariable %_ptr_float Function\n" +
5385 "%ld = OpLoad %float %n\n" +
5386 "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" +
5387 "%2 = OpFOrdLessThan %bool %clamp %float_1\n" +
5388 "OpReturn\n" +
5389 "OpFunctionEnd",
5390 2, 0),
5391 // Test case 10: Don't Fold clamp(-1, 0) > -1
5392 InstructionFoldingCase<uint32_t>(
5393 Header() + "%main = OpFunction %void None %void_func\n" +
5394 "%main_lab = OpLabel\n" +
5395 "%n = OpVariable %_ptr_float Function\n" +
5396 "%ld = OpLoad %float %n\n" +
5397 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5398 "%2 = OpFUnordGreaterThan %bool %clamp %float_n1\n" +
5399 "OpReturn\n" +
5400 "OpFunctionEnd",
5401 2, 0),
5402 // Test case 11: Don't Fold clamp(-1, 0) > -1
5403 InstructionFoldingCase<uint32_t>(
5404 Header() + "%main = OpFunction %void None %void_func\n" +
5405 "%main_lab = OpLabel\n" +
5406 "%n = OpVariable %_ptr_float Function\n" +
5407 "%ld = OpLoad %float %n\n" +
5408 "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" +
5409 "%2 = OpFOrdGreaterThan %bool %clamp %float_n1\n" +
5410 "OpReturn\n" +
5411 "OpFunctionEnd",
5412 2, 0)
5413 ));
5414
5415 INSTANTIATE_TEST_SUITE_P(FToIConstantFoldingTest, IntegerInstructionFoldingTest,
5416 ::testing::Values(
5417 // Test case 0: Fold int(3.0)
5418 InstructionFoldingCase<uint32_t>(
5419 Header() + "%main = OpFunction %void None %void_func\n" +
5420 "%main_lab = OpLabel\n" +
5421 "%2 = OpConvertFToS %int %float_3\n" +
5422 "OpReturn\n" +
5423 "OpFunctionEnd",
5424 2, 3),
5425 // Test case 1: Fold uint(3.0)
5426 InstructionFoldingCase<uint32_t>(
5427 Header() + "%main = OpFunction %void None %void_func\n" +
5428 "%main_lab = OpLabel\n" +
5429 "%2 = OpConvertFToU %int %float_3\n" +
5430 "OpReturn\n" +
5431 "OpFunctionEnd",
5432 2, 3)
5433 ));
5434
5435 INSTANTIATE_TEST_SUITE_P(IToFConstantFoldingTest, FloatInstructionFoldingTest,
5436 ::testing::Values(
5437 // Test case 0: Fold float(3)
5438 InstructionFoldingCase<float>(
5439 Header() + "%main = OpFunction %void None %void_func\n" +
5440 "%main_lab = OpLabel\n" +
5441 "%2 = OpConvertSToF %float %int_3\n" +
5442 "OpReturn\n" +
5443 "OpFunctionEnd",
5444 2, 3.0),
5445 // Test case 1: Fold float(3u)
5446 InstructionFoldingCase<float>(
5447 Header() + "%main = OpFunction %void None %void_func\n" +
5448 "%main_lab = OpLabel\n" +
5449 "%2 = OpConvertUToF %float %uint_3\n" +
5450 "OpReturn\n" +
5451 "OpFunctionEnd",
5452 2, 3.0)
5453 ));
5454 // clang-format on
5455
5456 using ToNegateFoldingTest =
5457 ::testing::TestWithParam<InstructionFoldingCase<uint32_t>>;
5458
TEST_P(ToNegateFoldingTest,Case)5459 TEST_P(ToNegateFoldingTest, Case) {
5460 const auto& tc = GetParam();
5461
5462 std::unique_ptr<IRContext> context;
5463 Instruction* inst;
5464 std::tie(context, inst) =
5465 FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_1);
5466
5467 EXPECT_TRUE((inst == nullptr) == (tc.expected_result == 0));
5468 if (inst != nullptr) {
5469 EXPECT_EQ(inst->opcode(), spv::Op::OpFNegate);
5470 EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
5471 }
5472 }
5473
5474 // clang-format off
5475 INSTANTIATE_TEST_SUITE_P(FloatRedundantSubFoldingTest, ToNegateFoldingTest,
5476 ::testing::Values(
5477 // Test case 0: Don't fold 1.0 - n
5478 InstructionFoldingCase<uint32_t>(
5479 Header() + "%main = OpFunction %void None %void_func\n" +
5480 "%main_lab = OpLabel\n" +
5481 "%n = OpVariable %_ptr_float Function\n" +
5482 "%3 = OpLoad %float %n\n" +
5483 "%2 = OpFSub %float %float_1 %3\n" +
5484 "OpReturn\n" +
5485 "OpFunctionEnd",
5486 2, 0),
5487 // Test case 1: Fold 0.0 - n
5488 InstructionFoldingCase<uint32_t>(
5489 Header() + "%main = OpFunction %void None %void_func\n" +
5490 "%main_lab = OpLabel\n" +
5491 "%n = OpVariable %_ptr_float Function\n" +
5492 "%3 = OpLoad %float %n\n" +
5493 "%2 = OpFSub %float %float_0 %3\n" +
5494 "OpReturn\n" +
5495 "OpFunctionEnd",
5496 2, 3),
5497 // Test case 2: Don't fold (0,0,0,1) - n
5498 InstructionFoldingCase<uint32_t>(
5499 Header() + "%main = OpFunction %void None %void_func\n" +
5500 "%main_lab = OpLabel\n" +
5501 "%n = OpVariable %_ptr_v4float Function\n" +
5502 "%3 = OpLoad %v4float %n\n" +
5503 "%2 = OpFSub %v4float %v4float_0_0_0_1 %3\n" +
5504 "OpReturn\n" +
5505 "OpFunctionEnd",
5506 2, 0),
5507 // Test case 3: Fold (0,0,0,0) - n
5508 InstructionFoldingCase<uint32_t>(
5509 Header() + "%main = OpFunction %void None %void_func\n" +
5510 "%main_lab = OpLabel\n" +
5511 "%n = OpVariable %_ptr_v4float Function\n" +
5512 "%3 = OpLoad %v4float %n\n" +
5513 "%2 = OpFSub %v4float %v4float_0_0_0_0 %3\n" +
5514 "OpReturn\n" +
5515 "OpFunctionEnd",
5516 2, 3)
5517 ));
5518
5519 INSTANTIATE_TEST_SUITE_P(DoubleRedundantSubFoldingTest, ToNegateFoldingTest,
5520 ::testing::Values(
5521 // Test case 0: Don't fold 1.0 - n
5522 InstructionFoldingCase<uint32_t>(
5523 Header() + "%main = OpFunction %void None %void_func\n" +
5524 "%main_lab = OpLabel\n" +
5525 "%n = OpVariable %_ptr_double Function\n" +
5526 "%3 = OpLoad %double %n\n" +
5527 "%2 = OpFSub %double %double_1 %3\n" +
5528 "OpReturn\n" +
5529 "OpFunctionEnd",
5530 2, 0),
5531 // Test case 1: Fold 0.0 - n
5532 InstructionFoldingCase<uint32_t>(
5533 Header() + "%main = OpFunction %void None %void_func\n" +
5534 "%main_lab = OpLabel\n" +
5535 "%n = OpVariable %_ptr_double Function\n" +
5536 "%3 = OpLoad %double %n\n" +
5537 "%2 = OpFSub %double %double_0 %3\n" +
5538 "OpReturn\n" +
5539 "OpFunctionEnd",
5540 2, 3),
5541 // Test case 2: Don't fold (0,0,0,1) - n
5542 InstructionFoldingCase<uint32_t>(
5543 Header() + "%main = OpFunction %void None %void_func\n" +
5544 "%main_lab = OpLabel\n" +
5545 "%n = OpVariable %_ptr_v4double Function\n" +
5546 "%3 = OpLoad %v4double %n\n" +
5547 "%2 = OpFSub %v4double %v4double_0_0_0_1 %3\n" +
5548 "OpReturn\n" +
5549 "OpFunctionEnd",
5550 2, 0),
5551 // Test case 3: Fold (0,0,0,0) - n
5552 InstructionFoldingCase<uint32_t>(
5553 Header() + "%main = OpFunction %void None %void_func\n" +
5554 "%main_lab = OpLabel\n" +
5555 "%n = OpVariable %_ptr_v4double Function\n" +
5556 "%3 = OpLoad %v4double %n\n" +
5557 "%2 = OpFSub %v4double %v4double_0_0_0_0 %3\n" +
5558 "OpReturn\n" +
5559 "OpFunctionEnd",
5560 2, 3)
5561 ));
5562
5563 using MatchingInstructionFoldingTest =
5564 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
5565
TEST_P(MatchingInstructionFoldingTest,Case)5566 TEST_P(MatchingInstructionFoldingTest, Case) {
5567 const auto& tc = GetParam();
5568
5569 std::unique_ptr<IRContext> context;
5570 Instruction* inst;
5571 std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
5572
5573 EXPECT_EQ(inst != nullptr, tc.expected_result);
5574 if (inst != nullptr) {
5575 Match(tc.test_body, context.get());
5576 }
5577 }
5578
5579 INSTANTIATE_TEST_SUITE_P(RedundantIntegerMatching, MatchingInstructionFoldingTest,
5580 ::testing::Values(
5581 // Test case 0: Fold 0 + n (change sign)
5582 InstructionFoldingCase<bool>(
5583 Header() +
5584 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
5585 "; CHECK: %2 = OpBitcast [[uint]] %3\n" +
5586 "%main = OpFunction %void None %void_func\n" +
5587 "%main_lab = OpLabel\n" +
5588 "%n = OpVariable %_ptr_int Function\n" +
5589 "%3 = OpLoad %uint %n\n" +
5590 "%2 = OpIAdd %uint %int_0 %3\n" +
5591 "OpReturn\n" +
5592 "OpFunctionEnd\n",
5593 2, true),
5594 // Test case 0: Fold 0 + n (change sign)
5595 InstructionFoldingCase<bool>(
5596 Header() +
5597 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5598 "; CHECK: %2 = OpBitcast [[int]] %3\n" +
5599 "%main = OpFunction %void None %void_func\n" +
5600 "%main_lab = OpLabel\n" +
5601 "%n = OpVariable %_ptr_int Function\n" +
5602 "%3 = OpLoad %int %n\n" +
5603 "%2 = OpIAdd %int %uint_0 %3\n" +
5604 "OpReturn\n" +
5605 "OpFunctionEnd\n",
5606 2, true)
5607 ));
5608
5609 INSTANTIATE_TEST_SUITE_P(MergeNegateTest, MatchingInstructionFoldingTest,
5610 ::testing::Values(
5611 // Test case 0: fold consecutive fnegate
5612 // -(-x) = x
5613 InstructionFoldingCase<bool>(
5614 Header() +
5615 "; CHECK: [[ld:%\\w+]] = OpLoad [[float:%\\w+]]\n" +
5616 "; CHECK: %4 = OpCopyObject [[float]] [[ld]]\n" +
5617 "%main = OpFunction %void None %void_func\n" +
5618 "%main_lab = OpLabel\n" +
5619 "%var = OpVariable %_ptr_float Function\n" +
5620 "%2 = OpLoad %float %var\n" +
5621 "%3 = OpFNegate %float %2\n" +
5622 "%4 = OpFNegate %float %3\n" +
5623 "OpReturn\n" +
5624 "OpFunctionEnd",
5625 4, true),
5626 // Test case 1: fold fnegate(fmul with const).
5627 // -(x * 2.0) = x * -2.0
5628 InstructionFoldingCase<bool>(
5629 Header() +
5630 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5631 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5632 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5633 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
5634 "%main = OpFunction %void None %void_func\n" +
5635 "%main_lab = OpLabel\n" +
5636 "%var = OpVariable %_ptr_float Function\n" +
5637 "%2 = OpLoad %float %var\n" +
5638 "%3 = OpFMul %float %2 %float_2\n" +
5639 "%4 = OpFNegate %float %3\n" +
5640 "OpReturn\n" +
5641 "OpFunctionEnd",
5642 4, true),
5643 // Test case 2: fold fnegate(fmul with const).
5644 // -(2.0 * x) = x * 2.0
5645 InstructionFoldingCase<bool>(
5646 Header() +
5647 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5648 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5649 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5650 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n2]]\n" +
5651 "%main = OpFunction %void None %void_func\n" +
5652 "%main_lab = OpLabel\n" +
5653 "%var = OpVariable %_ptr_float Function\n" +
5654 "%2 = OpLoad %float %var\n" +
5655 "%3 = OpFMul %float %float_2 %2\n" +
5656 "%4 = OpFNegate %float %3\n" +
5657 "OpReturn\n" +
5658 "OpFunctionEnd",
5659 4, true),
5660 // Test case 3: fold fnegate(fdiv with const).
5661 // -(x / 2.0) = x * -0.5
5662 InstructionFoldingCase<bool>(
5663 Header() +
5664 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5665 "; CHECK: [[float_n0p5:%\\w+]] = OpConstant [[float]] -0.5\n" +
5666 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5667 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_n0p5]]\n" +
5668 "%main = OpFunction %void None %void_func\n" +
5669 "%main_lab = OpLabel\n" +
5670 "%var = OpVariable %_ptr_float Function\n" +
5671 "%2 = OpLoad %float %var\n" +
5672 "%3 = OpFDiv %float %2 %float_2\n" +
5673 "%4 = OpFNegate %float %3\n" +
5674 "OpReturn\n" +
5675 "OpFunctionEnd",
5676 4, true),
5677 // Test case 4: fold fnegate(fdiv with const).
5678 // -(2.0 / x) = -2.0 / x
5679 InstructionFoldingCase<bool>(
5680 Header() +
5681 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5682 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5683 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5684 "; CHECK: %4 = OpFDiv [[float]] [[float_n2]] [[ld]]\n" +
5685 "%main = OpFunction %void None %void_func\n" +
5686 "%main_lab = OpLabel\n" +
5687 "%var = OpVariable %_ptr_float Function\n" +
5688 "%2 = OpLoad %float %var\n" +
5689 "%3 = OpFDiv %float %float_2 %2\n" +
5690 "%4 = OpFNegate %float %3\n" +
5691 "OpReturn\n" +
5692 "OpFunctionEnd",
5693 4, true),
5694 // Test case 5: fold fnegate(fadd with const).
5695 // -(2.0 + x) = -2.0 - x
5696 InstructionFoldingCase<bool>(
5697 Header() +
5698 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5699 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5700 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5701 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
5702 "%main = OpFunction %void None %void_func\n" +
5703 "%main_lab = OpLabel\n" +
5704 "%var = OpVariable %_ptr_float Function\n" +
5705 "%2 = OpLoad %float %var\n" +
5706 "%3 = OpFAdd %float %float_2 %2\n" +
5707 "%4 = OpFNegate %float %3\n" +
5708 "OpReturn\n" +
5709 "OpFunctionEnd",
5710 4, true),
5711 // Test case 6: fold fnegate(fadd with const).
5712 // -(x + 2.0) = -2.0 - x
5713 InstructionFoldingCase<bool>(
5714 Header() +
5715 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5716 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5717 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5718 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
5719 "%main = OpFunction %void None %void_func\n" +
5720 "%main_lab = OpLabel\n" +
5721 "%var = OpVariable %_ptr_float Function\n" +
5722 "%2 = OpLoad %float %var\n" +
5723 "%3 = OpFAdd %float %2 %float_2\n" +
5724 "%4 = OpFNegate %float %3\n" +
5725 "OpReturn\n" +
5726 "OpFunctionEnd",
5727 4, true),
5728 // Test case 7: fold fnegate(fsub with const).
5729 // -(2.0 - x) = x - 2.0
5730 InstructionFoldingCase<bool>(
5731 Header() +
5732 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5733 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5734 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5735 "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_2]]\n" +
5736 "%main = OpFunction %void None %void_func\n" +
5737 "%main_lab = OpLabel\n" +
5738 "%var = OpVariable %_ptr_float Function\n" +
5739 "%2 = OpLoad %float %var\n" +
5740 "%3 = OpFSub %float %float_2 %2\n" +
5741 "%4 = OpFNegate %float %3\n" +
5742 "OpReturn\n" +
5743 "OpFunctionEnd",
5744 4, true),
5745 // Test case 8: fold fnegate(fsub with const).
5746 // -(x - 2.0) = 2.0 - x
5747 InstructionFoldingCase<bool>(
5748 Header() +
5749 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5750 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
5751 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
5752 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
5753 "%main = OpFunction %void None %void_func\n" +
5754 "%main_lab = OpLabel\n" +
5755 "%var = OpVariable %_ptr_float Function\n" +
5756 "%2 = OpLoad %float %var\n" +
5757 "%3 = OpFSub %float %2 %float_2\n" +
5758 "%4 = OpFNegate %float %3\n" +
5759 "OpReturn\n" +
5760 "OpFunctionEnd",
5761 4, true),
5762 // Test case 9: fold consecutive snegate
5763 // -(-x) = x
5764 InstructionFoldingCase<bool>(
5765 Header() +
5766 "; CHECK: [[ld:%\\w+]] = OpLoad [[int:%\\w+]]\n" +
5767 "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
5768 "%main = OpFunction %void None %void_func\n" +
5769 "%main_lab = OpLabel\n" +
5770 "%var = OpVariable %_ptr_int Function\n" +
5771 "%2 = OpLoad %int %var\n" +
5772 "%3 = OpSNegate %int %2\n" +
5773 "%4 = OpSNegate %int %3\n" +
5774 "OpReturn\n" +
5775 "OpFunctionEnd",
5776 4, true),
5777 // Test case 10: fold consecutive vector negate
5778 // -(-x) = x
5779 InstructionFoldingCase<bool>(
5780 Header() +
5781 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float:%\\w+]]\n" +
5782 "; CHECK: %4 = OpCopyObject [[v2float]] [[ld]]\n" +
5783 "%main = OpFunction %void None %void_func\n" +
5784 "%main_lab = OpLabel\n" +
5785 "%var = OpVariable %_ptr_v2float Function\n" +
5786 "%2 = OpLoad %v2float %var\n" +
5787 "%3 = OpFNegate %v2float %2\n" +
5788 "%4 = OpFNegate %v2float %3\n" +
5789 "OpReturn\n" +
5790 "OpFunctionEnd",
5791 4, true),
5792 // Test case 11: fold snegate(iadd with const).
5793 // -(2 + x) = -2 - x
5794 InstructionFoldingCase<bool>(
5795 Header() +
5796 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5797 "; CHECK: OpConstant [[int]] -2147483648\n" +
5798 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
5799 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5800 "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
5801 "%main = OpFunction %void None %void_func\n" +
5802 "%main_lab = OpLabel\n" +
5803 "%var = OpVariable %_ptr_int Function\n" +
5804 "%2 = OpLoad %int %var\n" +
5805 "%3 = OpIAdd %int %int_2 %2\n" +
5806 "%4 = OpSNegate %int %3\n" +
5807 "OpReturn\n" +
5808 "OpFunctionEnd",
5809 4, true),
5810 // Test case 12: fold snegate(iadd with const).
5811 // -(x + 2) = -2 - x
5812 InstructionFoldingCase<bool>(
5813 Header() +
5814 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5815 "; CHECK: OpConstant [[int]] -2147483648\n" +
5816 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
5817 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5818 "; CHECK: %4 = OpISub [[int]] [[int_n2]] [[ld]]\n" +
5819 "%main = OpFunction %void None %void_func\n" +
5820 "%main_lab = OpLabel\n" +
5821 "%var = OpVariable %_ptr_int Function\n" +
5822 "%2 = OpLoad %int %var\n" +
5823 "%3 = OpIAdd %int %2 %int_2\n" +
5824 "%4 = OpSNegate %int %3\n" +
5825 "OpReturn\n" +
5826 "OpFunctionEnd",
5827 4, true),
5828 // Test case 13: fold snegate(isub with const).
5829 // -(2 - x) = x - 2
5830 InstructionFoldingCase<bool>(
5831 Header() +
5832 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5833 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
5834 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5835 "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_2]]\n" +
5836 "%main = OpFunction %void None %void_func\n" +
5837 "%main_lab = OpLabel\n" +
5838 "%var = OpVariable %_ptr_int Function\n" +
5839 "%2 = OpLoad %int %var\n" +
5840 "%3 = OpISub %int %int_2 %2\n" +
5841 "%4 = OpSNegate %int %3\n" +
5842 "OpReturn\n" +
5843 "OpFunctionEnd",
5844 4, true),
5845 // Test case 14: fold snegate(isub with const).
5846 // -(x - 2) = 2 - x
5847 InstructionFoldingCase<bool>(
5848 Header() +
5849 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5850 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
5851 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5852 "; CHECK: %4 = OpISub [[int]] [[int_2]] [[ld]]\n" +
5853 "%main = OpFunction %void None %void_func\n" +
5854 "%main_lab = OpLabel\n" +
5855 "%var = OpVariable %_ptr_int Function\n" +
5856 "%2 = OpLoad %int %var\n" +
5857 "%3 = OpISub %int %2 %int_2\n" +
5858 "%4 = OpSNegate %int %3\n" +
5859 "OpReturn\n" +
5860 "OpFunctionEnd",
5861 4, true),
5862 // Test case 15: fold snegate(iadd with const).
5863 // -(x + 2) = -2 - x
5864 InstructionFoldingCase<bool>(
5865 Header() +
5866 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5867 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
5868 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5869 "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
5870 "%main = OpFunction %void None %void_func\n" +
5871 "%main_lab = OpLabel\n" +
5872 "%var = OpVariable %_ptr_long Function\n" +
5873 "%2 = OpLoad %long %var\n" +
5874 "%3 = OpIAdd %long %2 %long_2\n" +
5875 "%4 = OpSNegate %long %3\n" +
5876 "OpReturn\n" +
5877 "OpFunctionEnd",
5878 4, true),
5879 // Test case 16: fold snegate(isub with const).
5880 // -(2 - x) = x - 2
5881 InstructionFoldingCase<bool>(
5882 Header() +
5883 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5884 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5885 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5886 "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_2]]\n" +
5887 "%main = OpFunction %void None %void_func\n" +
5888 "%main_lab = OpLabel\n" +
5889 "%var = OpVariable %_ptr_long Function\n" +
5890 "%2 = OpLoad %long %var\n" +
5891 "%3 = OpISub %long %long_2 %2\n" +
5892 "%4 = OpSNegate %long %3\n" +
5893 "OpReturn\n" +
5894 "OpFunctionEnd",
5895 4, true),
5896 // Test case 17: fold snegate(isub with const).
5897 // -(x - 2) = 2 - x
5898 InstructionFoldingCase<bool>(
5899 Header() +
5900 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5901 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
5902 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5903 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
5904 "%main = OpFunction %void None %void_func\n" +
5905 "%main_lab = OpLabel\n" +
5906 "%var = OpVariable %_ptr_long Function\n" +
5907 "%2 = OpLoad %long %var\n" +
5908 "%3 = OpISub %long %2 %long_2\n" +
5909 "%4 = OpSNegate %long %3\n" +
5910 "OpReturn\n" +
5911 "OpFunctionEnd",
5912 4, true),
5913 // Test case 18: fold -vec4(-1.0, 2.0, 1.0, 3.0)
5914 InstructionFoldingCase<bool>(
5915 Header() +
5916 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
5917 "; CHECK: [[v4float:%\\w+]] = OpTypeVector [[float]] 4{{[[:space:]]}}\n" +
5918 "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1{{[[:space:]]}}\n" +
5919 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1{{[[:space:]]}}\n" +
5920 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
5921 "; CHECK: [[float_n3:%\\w+]] = OpConstant [[float]] -3{{[[:space:]]}}\n" +
5922 "; CHECK: [[v4float_1_n2_n1_n3:%\\w+]] = OpConstantComposite [[v4float]] [[float_1]] [[float_n2]] [[float_n1]] [[float_n3]]\n" +
5923 "; CHECK: %2 = OpCopyObject [[v4float]] [[v4float_1_n2_n1_n3]]\n" +
5924 "%main = OpFunction %void None %void_func\n" +
5925 "%main_lab = OpLabel\n" +
5926 "%2 = OpFNegate %v4float %v4float_n1_2_1_3\n" +
5927 "OpReturn\n" +
5928 "OpFunctionEnd",
5929 2, true),
5930 // Test case 19: fold vector fnegate with null
5931 InstructionFoldingCase<bool>(
5932 Header() +
5933 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
5934 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
5935 "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" +
5936 "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_n0]] [[double_n0]]\n" +
5937 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
5938 "%main = OpFunction %void None %void_func\n" +
5939 "%main_lab = OpLabel\n" +
5940 "%2 = OpFNegate %v2double %v2double_null\n" +
5941 "OpReturn\n" +
5942 "OpFunctionEnd",
5943 2, true),
5944 // Test case 20: fold snegate with OpIMul.
5945 // -(x * 2) = x * -2
5946 InstructionFoldingCase<bool>(
5947 Header() +
5948 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
5949 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2\n" +
5950 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
5951 "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_n2]]\n" +
5952 "%main = OpFunction %void None %void_func\n" +
5953 "%main_lab = OpLabel\n" +
5954 "%var = OpVariable %_ptr_long Function\n" +
5955 "%2 = OpLoad %long %var\n" +
5956 "%3 = OpIMul %long %2 %long_2\n" +
5957 "%4 = OpSNegate %long %3\n" +
5958 "OpReturn\n" +
5959 "OpFunctionEnd",
5960 4, true),
5961 // Test case 21: fold snegate with OpIMul.
5962 // -(x * 2) = x * -2
5963 InstructionFoldingCase<bool>(
5964 Header() +
5965 "; CHECK-DAG: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5966 "; CHECK-DAG: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
5967 "; CHECK: [[uint_n2:%\\w+]] = OpConstant [[uint]] 4294967294\n" +
5968 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5969 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[uint_n2]]\n" +
5970 "%main = OpFunction %void None %void_func\n" +
5971 "%main_lab = OpLabel\n" +
5972 "%var = OpVariable %_ptr_int Function\n" +
5973 "%2 = OpLoad %int %var\n" +
5974 "%3 = OpIMul %int %2 %uint_2\n" +
5975 "%4 = OpSNegate %int %3\n" +
5976 "OpReturn\n" +
5977 "OpFunctionEnd",
5978 4, true),
5979 // Test case 22: fold snegate with OpIMul.
5980 // -(-24 * x) = x * 24
5981 InstructionFoldingCase<bool>(
5982 Header() +
5983 "; CHECK-DAG: [[int:%\\w+]] = OpTypeInt 32 1\n" +
5984 "; CHECK: [[int_24:%\\w+]] = OpConstant [[int]] 24\n" +
5985 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
5986 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_24]]\n" +
5987 "%main = OpFunction %void None %void_func\n" +
5988 "%main_lab = OpLabel\n" +
5989 "%var = OpVariable %_ptr_int Function\n" +
5990 "%2 = OpLoad %int %var\n" +
5991 "%3 = OpIMul %int %int_n24 %2\n" +
5992 "%4 = OpSNegate %int %3\n" +
5993 "OpReturn\n" +
5994 "OpFunctionEnd",
5995 4, true),
5996 // Test case 23: fold snegate with OpIMul with UINT_MAX
5997 // -(UINT_MAX * x) = x
5998 InstructionFoldingCase<bool>(
5999 Header() +
6000 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6001 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6002 "; CHECK: %4 = OpCopyObject [[int]] [[ld]]\n" +
6003 "%main = OpFunction %void None %void_func\n" +
6004 "%main_lab = OpLabel\n" +
6005 "%var = OpVariable %_ptr_int Function\n" +
6006 "%2 = OpLoad %int %var\n" +
6007 "%3 = OpIMul %int %uint_max %2\n" +
6008 "%4 = OpSNegate %int %3\n" +
6009 "OpReturn\n" +
6010 "OpFunctionEnd",
6011 4, true),
6012 // Test case 24: fold snegate with OpIMul using -INT_MAX
6013 // -(x * 2147483649u) = x * 2147483647u
6014 InstructionFoldingCase<bool>(
6015 Header() +
6016 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6017 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
6018 "; CHECK: [[uint_2147483647:%\\w+]] = OpConstant [[uint]] 2147483647\n" +
6019 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6020 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[uint_2147483647]]\n" +
6021 "%main = OpFunction %void None %void_func\n" +
6022 "%main_lab = OpLabel\n" +
6023 "%var = OpVariable %_ptr_int Function\n" +
6024 "%2 = OpLoad %int %var\n" +
6025 "%3 = OpIMul %int %2 %uint_2147483649\n" +
6026 "%4 = OpSNegate %int %3\n" +
6027 "OpReturn\n" +
6028 "OpFunctionEnd",
6029 4, true),
6030 // Test case 25: fold snegate with OpSDiv (long).
6031 // -(x / 2) = x / -2
6032 InstructionFoldingCase<bool>(
6033 Header() +
6034 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
6035 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2\n" +
6036 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6037 "; CHECK: %4 = OpSDiv [[long]] [[ld]] [[long_n2]]\n" +
6038 "%main = OpFunction %void None %void_func\n" +
6039 "%main_lab = OpLabel\n" +
6040 "%var = OpVariable %_ptr_long Function\n" +
6041 "%2 = OpLoad %long %var\n" +
6042 "%3 = OpSDiv %long %2 %long_2\n" +
6043 "%4 = OpSNegate %long %3\n" +
6044 "OpReturn\n" +
6045 "OpFunctionEnd",
6046 4, true),
6047 // Test case 26: fold snegate with OpSDiv (int).
6048 // -(x / 2) = x / -2
6049 InstructionFoldingCase<bool>(
6050 Header() +
6051 "; CHECK-DAG: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6052 "; CHECK-DAG: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
6053 "; CHECK: [[uint_n2:%\\w+]] = OpConstant [[uint]] 4294967294\n" +
6054 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6055 "; CHECK: %4 = OpSDiv [[int]] [[ld]] [[uint_n2]]\n" +
6056 "%main = OpFunction %void None %void_func\n" +
6057 "%main_lab = OpLabel\n" +
6058 "%var = OpVariable %_ptr_int Function\n" +
6059 "%2 = OpLoad %int %var\n" +
6060 "%3 = OpSDiv %int %2 %uint_2\n" +
6061 "%4 = OpSNegate %int %3\n" +
6062 "OpReturn\n" +
6063 "OpFunctionEnd",
6064 4, true),
6065 // Test case 27: fold snegate with OpSDiv.
6066 // -(-24 / x) = 24 / x
6067 InstructionFoldingCase<bool>(
6068 Header() +
6069 "; CHECK-DAG: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6070 "; CHECK: [[int_24:%\\w+]] = OpConstant [[int]] 24\n" +
6071 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6072 "; CHECK: %4 = OpSDiv [[int]] [[int_24]] [[ld]]\n" +
6073 "%main = OpFunction %void None %void_func\n" +
6074 "%main_lab = OpLabel\n" +
6075 "%var = OpVariable %_ptr_int Function\n" +
6076 "%2 = OpLoad %int %var\n" +
6077 "%3 = OpSDiv %int %int_n24 %2\n" +
6078 "%4 = OpSNegate %int %3\n" +
6079 "OpReturn\n" +
6080 "OpFunctionEnd",
6081 4, true),
6082 // Test case 28: fold snegate with OpSDiv with UINT_MAX
6083 // -(UINT_MAX / x) = (1 / x)
6084 InstructionFoldingCase<bool>(
6085 Header() +
6086 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6087 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
6088 "; CHECK: [[uint_1:%\\w+]] = OpConstant [[uint]] 1\n" +
6089 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6090 "; CHECK: %4 = OpSDiv [[int]] [[uint_1]] [[ld]]\n" +
6091 "%main = OpFunction %void None %void_func\n" +
6092 "%main_lab = OpLabel\n" +
6093 "%var = OpVariable %_ptr_int Function\n" +
6094 "%2 = OpLoad %int %var\n" +
6095 "%3 = OpSDiv %int %uint_max %2\n" +
6096 "%4 = OpSNegate %int %3\n" +
6097 "OpReturn\n" +
6098 "OpFunctionEnd",
6099 4, true),
6100 // Test case 29: fold snegate with OpSDiv using -INT_MAX
6101 // -(x / 2147483647u) = x / 2147483647
6102 InstructionFoldingCase<bool>(
6103 Header() +
6104 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6105 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
6106 "; CHECK: [[uint_2147483647:%\\w+]] = OpConstant [[uint]] 2147483647\n" +
6107 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6108 "; CHECK: %4 = OpSDiv [[int]] [[ld]] [[uint_2147483647]]\n" +
6109 "%main = OpFunction %void None %void_func\n" +
6110 "%main_lab = OpLabel\n" +
6111 "%var = OpVariable %_ptr_int Function\n" +
6112 "%2 = OpLoad %int %var\n" +
6113 "%3 = OpSDiv %int %2 %uint_2147483649\n" +
6114 "%4 = OpSNegate %int %3\n" +
6115 "OpReturn\n" +
6116 "OpFunctionEnd",
6117 4, true),
6118 // Test case 30: Don't fold snegate int OpUDiv. The operands are interpreted
6119 // as unsigned, so negating an operand is not the same a negating the
6120 // result.
6121 InstructionFoldingCase<bool>(
6122 Header() +
6123 "%main = OpFunction %void None %void_func\n" +
6124 "%main_lab = OpLabel\n" +
6125 "%var = OpVariable %_ptr_int Function\n" +
6126 "%2 = OpLoad %int %var\n" +
6127 "%3 = OpUDiv %int %2 %uint_1\n" +
6128 "%4 = OpSNegate %int %3\n" +
6129 "OpReturn\n" +
6130 "OpFunctionEnd",
6131 4, false)
6132 ));
6133
6134 INSTANTIATE_TEST_SUITE_P(ReciprocalFDivTest, MatchingInstructionFoldingTest,
6135 ::testing::Values(
6136 // Test case 0: scalar reicprocal
6137 // x / 0.5 = x * 2.0
6138 InstructionFoldingCase<bool>(
6139 Header() +
6140 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6141 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6142 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6143 "; CHECK: %3 = OpFMul [[float]] [[ld]] [[float_2]]\n" +
6144 "%main = OpFunction %void None %void_func\n" +
6145 "%main_lab = OpLabel\n" +
6146 "%var = OpVariable %_ptr_float Function\n" +
6147 "%2 = OpLoad %float %var\n" +
6148 "%3 = OpFDiv %float %2 %float_0p5\n" +
6149 "OpReturn\n" +
6150 "OpFunctionEnd\n",
6151 3, true),
6152 // Test case 1: Unfoldable
6153 InstructionFoldingCase<bool>(
6154 Header() +
6155 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6156 "; CHECK: [[float_0:%\\w+]] = OpConstant [[float]] 0\n" +
6157 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6158 "; CHECK: %3 = OpFDiv [[float]] [[ld]] [[float_0]]\n" +
6159 "%main = OpFunction %void None %void_func\n" +
6160 "%main_lab = OpLabel\n" +
6161 "%var = OpVariable %_ptr_float Function\n" +
6162 "%2 = OpLoad %float %var\n" +
6163 "%3 = OpFDiv %float %2 %104\n" +
6164 "OpReturn\n" +
6165 "OpFunctionEnd\n",
6166 3, false),
6167 // Test case 2: Vector reciprocal
6168 // x / {2.0, 0.5} = x * {0.5, 2.0}
6169 InstructionFoldingCase<bool>(
6170 Header() +
6171 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6172 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6173 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6174 "; CHECK: [[float_0p5:%\\w+]] = OpConstant [[float]] 0.5\n" +
6175 "; CHECK: [[v2float_0p5_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_0p5]] [[float_2]]\n" +
6176 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
6177 "; CHECK: %3 = OpFMul [[v2float]] [[ld]] [[v2float_0p5_2]]\n" +
6178 "%main = OpFunction %void None %void_func\n" +
6179 "%main_lab = OpLabel\n" +
6180 "%var = OpVariable %_ptr_v2float Function\n" +
6181 "%2 = OpLoad %v2float %var\n" +
6182 "%3 = OpFDiv %v2float %2 %v2float_2_0p5\n" +
6183 "OpReturn\n" +
6184 "OpFunctionEnd\n",
6185 3, true),
6186 // Test case 3: double reciprocal
6187 // x / 2.0 = x * 0.5
6188 InstructionFoldingCase<bool>(
6189 Header() +
6190 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6191 "; CHECK: [[double_0p5:%\\w+]] = OpConstant [[double]] 0.5\n" +
6192 "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
6193 "; CHECK: %3 = OpFMul [[double]] [[ld]] [[double_0p5]]\n" +
6194 "%main = OpFunction %void None %void_func\n" +
6195 "%main_lab = OpLabel\n" +
6196 "%var = OpVariable %_ptr_double Function\n" +
6197 "%2 = OpLoad %double %var\n" +
6198 "%3 = OpFDiv %double %2 %double_2\n" +
6199 "OpReturn\n" +
6200 "OpFunctionEnd\n",
6201 3, true),
6202 // Test case 4: don't fold x / 0.
6203 InstructionFoldingCase<bool>(
6204 Header() +
6205 "%main = OpFunction %void None %void_func\n" +
6206 "%main_lab = OpLabel\n" +
6207 "%var = OpVariable %_ptr_v2float Function\n" +
6208 "%2 = OpLoad %v2float %var\n" +
6209 "%3 = OpFDiv %v2float %2 %v2float_null\n" +
6210 "OpReturn\n" +
6211 "OpFunctionEnd\n",
6212 3, false)
6213 ));
6214
6215 INSTANTIATE_TEST_SUITE_P(MergeMulTest, MatchingInstructionFoldingTest,
6216 ::testing::Values(
6217 // Test case 0: fold consecutive fmuls
6218 // (x * 3.0) * 2.0 = x * 6.0
6219 InstructionFoldingCase<bool>(
6220 Header() +
6221 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6222 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
6223 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6224 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
6225 "%main = OpFunction %void None %void_func\n" +
6226 "%main_lab = OpLabel\n" +
6227 "%var = OpVariable %_ptr_float Function\n" +
6228 "%2 = OpLoad %float %var\n" +
6229 "%3 = OpFMul %float %2 %float_3\n" +
6230 "%4 = OpFMul %float %3 %float_2\n" +
6231 "OpReturn\n" +
6232 "OpFunctionEnd\n",
6233 4, true),
6234 // Test case 1: fold consecutive fmuls
6235 // 2.0 * (x * 3.0) = x * 6.0
6236 InstructionFoldingCase<bool>(
6237 Header() +
6238 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6239 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
6240 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6241 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
6242 "%main = OpFunction %void None %void_func\n" +
6243 "%main_lab = OpLabel\n" +
6244 "%var = OpVariable %_ptr_float Function\n" +
6245 "%2 = OpLoad %float %var\n" +
6246 "%3 = OpFMul %float %2 %float_3\n" +
6247 "%4 = OpFMul %float %float_2 %3\n" +
6248 "OpReturn\n" +
6249 "OpFunctionEnd\n",
6250 4, true),
6251 // Test case 2: fold consecutive fmuls
6252 // (3.0 * x) * 2.0 = x * 6.0
6253 InstructionFoldingCase<bool>(
6254 Header() +
6255 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6256 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
6257 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6258 "; CHECK: %4 = OpFMul [[float]] [[ld]] [[float_6]]\n" +
6259 "%main = OpFunction %void None %void_func\n" +
6260 "%main_lab = OpLabel\n" +
6261 "%var = OpVariable %_ptr_float Function\n" +
6262 "%2 = OpLoad %float %var\n" +
6263 "%3 = OpFMul %float %float_3 %2\n" +
6264 "%4 = OpFMul %float %float_2 %3\n" +
6265 "OpReturn\n" +
6266 "OpFunctionEnd\n",
6267 4, true),
6268 // Test case 3: fold vector fmul
6269 InstructionFoldingCase<bool>(
6270 Header() +
6271 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6272 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6273 "; CHECK: [[float_6:%\\w+]] = OpConstant [[float]] 6\n" +
6274 "; CHECK: [[v2float_6_6:%\\w+]] = OpConstantComposite [[v2float]] [[float_6]] [[float_6]]\n" +
6275 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
6276 "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_6_6]]\n" +
6277 "%main = OpFunction %void None %void_func\n" +
6278 "%main_lab = OpLabel\n" +
6279 "%var = OpVariable %_ptr_v2float Function\n" +
6280 "%2 = OpLoad %v2float %var\n" +
6281 "%3 = OpFMul %v2float %2 %v2float_2_3\n" +
6282 "%4 = OpFMul %v2float %3 %v2float_3_2\n" +
6283 "OpReturn\n" +
6284 "OpFunctionEnd\n",
6285 4, true),
6286 // Test case 4: fold double fmuls
6287 // (x * 3.0) * 2.0 = x * 6.0
6288 InstructionFoldingCase<bool>(
6289 Header() +
6290 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6291 "; CHECK: [[double_6:%\\w+]] = OpConstant [[double]] 6\n" +
6292 "; CHECK: [[ld:%\\w+]] = OpLoad [[double]]\n" +
6293 "; CHECK: %4 = OpFMul [[double]] [[ld]] [[double_6]]\n" +
6294 "%main = OpFunction %void None %void_func\n" +
6295 "%main_lab = OpLabel\n" +
6296 "%var = OpVariable %_ptr_double Function\n" +
6297 "%2 = OpLoad %double %var\n" +
6298 "%3 = OpFMul %double %2 %double_3\n" +
6299 "%4 = OpFMul %double %3 %double_2\n" +
6300 "OpReturn\n" +
6301 "OpFunctionEnd\n",
6302 4, true),
6303 // Test case 5: fold 32 bit imuls
6304 // (x * 3) * 2 = x * 6
6305 InstructionFoldingCase<bool>(
6306 Header() +
6307 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6308 "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
6309 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6310 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_6]]\n" +
6311 "%main = OpFunction %void None %void_func\n" +
6312 "%main_lab = OpLabel\n" +
6313 "%var = OpVariable %_ptr_int Function\n" +
6314 "%2 = OpLoad %int %var\n" +
6315 "%3 = OpIMul %int %2 %int_3\n" +
6316 "%4 = OpIMul %int %3 %int_2\n" +
6317 "OpReturn\n" +
6318 "OpFunctionEnd\n",
6319 4, true),
6320 // Test case 6: fold 64 bit imuls
6321 // (x * 3) * 2 = x * 6
6322 InstructionFoldingCase<bool>(
6323 Header() +
6324 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6325 "; CHECK: [[long_6:%\\w+]] = OpConstant [[long]] 6\n" +
6326 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6327 "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_6]]\n" +
6328 "%main = OpFunction %void None %void_func\n" +
6329 "%main_lab = OpLabel\n" +
6330 "%var = OpVariable %_ptr_long Function\n" +
6331 "%2 = OpLoad %long %var\n" +
6332 "%3 = OpIMul %long %2 %long_3\n" +
6333 "%4 = OpIMul %long %3 %long_2\n" +
6334 "OpReturn\n" +
6335 "OpFunctionEnd\n",
6336 4, true),
6337 // Test case 7: merge vector integer mults
6338 InstructionFoldingCase<bool>(
6339 Header() +
6340 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6341 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
6342 "; CHECK: [[int_6:%\\w+]] = OpConstant [[int]] 6\n" +
6343 "; CHECK: [[v2int_6_6:%\\w+]] = OpConstantComposite [[v2int]] [[int_6]] [[int_6]]\n" +
6344 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
6345 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_6_6]]\n" +
6346 "%main = OpFunction %void None %void_func\n" +
6347 "%main_lab = OpLabel\n" +
6348 "%var = OpVariable %_ptr_v2int Function\n" +
6349 "%2 = OpLoad %v2int %var\n" +
6350 "%3 = OpIMul %v2int %2 %v2int_2_3\n" +
6351 "%4 = OpIMul %v2int %3 %v2int_3_2\n" +
6352 "OpReturn\n" +
6353 "OpFunctionEnd\n",
6354 4, true),
6355 // Test case 8: merge fmul of fdiv
6356 // 2.0 * (2.0 / x) = 4.0 / x
6357 InstructionFoldingCase<bool>(
6358 Header() +
6359 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6360 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
6361 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6362 "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
6363 "%main = OpFunction %void None %void_func\n" +
6364 "%main_lab = OpLabel\n" +
6365 "%var = OpVariable %_ptr_float Function\n" +
6366 "%2 = OpLoad %float %var\n" +
6367 "%3 = OpFDiv %float %float_2 %2\n" +
6368 "%4 = OpFMul %float %float_2 %3\n" +
6369 "OpReturn\n" +
6370 "OpFunctionEnd\n",
6371 4, true),
6372 // Test case 9: merge fmul of fdiv
6373 // (2.0 / x) * 2.0 = 4.0 / x
6374 InstructionFoldingCase<bool>(
6375 Header() +
6376 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6377 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
6378 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6379 "; CHECK: %4 = OpFDiv [[float]] [[float_4]] [[ld]]\n" +
6380 "%main = OpFunction %void None %void_func\n" +
6381 "%main_lab = OpLabel\n" +
6382 "%var = OpVariable %_ptr_float Function\n" +
6383 "%2 = OpLoad %float %var\n" +
6384 "%3 = OpFDiv %float %float_2 %2\n" +
6385 "%4 = OpFMul %float %3 %float_2\n" +
6386 "OpReturn\n" +
6387 "OpFunctionEnd\n",
6388 4, true),
6389 // Test case 10: Do not merge imul of sdiv
6390 // 4 * (x / 2)
6391 InstructionFoldingCase<bool>(
6392 Header() +
6393 "%main = OpFunction %void None %void_func\n" +
6394 "%main_lab = OpLabel\n" +
6395 "%var = OpVariable %_ptr_int Function\n" +
6396 "%2 = OpLoad %int %var\n" +
6397 "%3 = OpSDiv %int %2 %int_2\n" +
6398 "%4 = OpIMul %int %int_4 %3\n" +
6399 "OpReturn\n" +
6400 "OpFunctionEnd\n",
6401 4, false),
6402 // Test case 11: Do not merge imul of sdiv
6403 // (x / 2) * 4
6404 InstructionFoldingCase<bool>(
6405 Header() +
6406 "%main = OpFunction %void None %void_func\n" +
6407 "%main_lab = OpLabel\n" +
6408 "%var = OpVariable %_ptr_int Function\n" +
6409 "%2 = OpLoad %int %var\n" +
6410 "%3 = OpSDiv %int %2 %int_2\n" +
6411 "%4 = OpIMul %int %3 %int_4\n" +
6412 "OpReturn\n" +
6413 "OpFunctionEnd\n",
6414 4, false),
6415 // Test case 12: Do not merge imul of udiv
6416 // 4 * (x / 2)
6417 InstructionFoldingCase<bool>(
6418 Header() +
6419 "%main = OpFunction %void None %void_func\n" +
6420 "%main_lab = OpLabel\n" +
6421 "%var = OpVariable %_ptr_uint Function\n" +
6422 "%2 = OpLoad %uint %var\n" +
6423 "%3 = OpUDiv %uint %2 %uint_2\n" +
6424 "%4 = OpIMul %uint %uint_4 %3\n" +
6425 "OpReturn\n" +
6426 "OpFunctionEnd\n",
6427 4, false),
6428 // Test case 13: Do not merge imul of udiv
6429 // (x / 2) * 4
6430 InstructionFoldingCase<bool>(
6431 Header() +
6432 "%main = OpFunction %void None %void_func\n" +
6433 "%main_lab = OpLabel\n" +
6434 "%var = OpVariable %_ptr_uint Function\n" +
6435 "%2 = OpLoad %uint %var\n" +
6436 "%3 = OpUDiv %uint %2 %uint_2\n" +
6437 "%4 = OpIMul %uint %3 %uint_4\n" +
6438 "OpReturn\n" +
6439 "OpFunctionEnd\n",
6440 4, false),
6441 // Test case 14: Don't fold
6442 // (x / 3) * 4
6443 InstructionFoldingCase<bool>(
6444 Header() +
6445 "%main = OpFunction %void None %void_func\n" +
6446 "%main_lab = OpLabel\n" +
6447 "%var = OpVariable %_ptr_uint Function\n" +
6448 "%2 = OpLoad %uint %var\n" +
6449 "%3 = OpUDiv %uint %2 %uint_3\n" +
6450 "%4 = OpIMul %uint %3 %uint_4\n" +
6451 "OpReturn\n" +
6452 "OpFunctionEnd\n",
6453 4, false),
6454 // Test case 15: merge vector fmul of fdiv
6455 // (x / {2,2}) * {4,4} = x * {2,2}
6456 InstructionFoldingCase<bool>(
6457 Header() +
6458 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6459 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6460 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6461 "; CHECK: [[v2float_2_2:%\\w+]] = OpConstantComposite [[v2float]] [[float_2]] [[float_2]]\n" +
6462 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2float]]\n" +
6463 "; CHECK: %4 = OpFMul [[v2float]] [[ld]] [[v2float_2_2]]\n" +
6464 "%main = OpFunction %void None %void_func\n" +
6465 "%main_lab = OpLabel\n" +
6466 "%var = OpVariable %_ptr_v2float Function\n" +
6467 "%2 = OpLoad %v2float %var\n" +
6468 "%3 = OpFDiv %v2float %2 %v2float_2_2\n" +
6469 "%4 = OpFMul %v2float %3 %v2float_4_4\n" +
6470 "OpReturn\n" +
6471 "OpFunctionEnd\n",
6472 4, true),
6473 // Test case 16: merge vector imul of snegate
6474 // (-x) * {2,2} = x * {-2,-2}
6475 InstructionFoldingCase<bool>(
6476 Header() +
6477 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6478 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
6479 "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
6480 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
6481 "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
6482 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
6483 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
6484 "%main = OpFunction %void None %void_func\n" +
6485 "%main_lab = OpLabel\n" +
6486 "%var = OpVariable %_ptr_v2int Function\n" +
6487 "%2 = OpLoad %v2int %var\n" +
6488 "%3 = OpSNegate %v2int %2\n" +
6489 "%4 = OpIMul %v2int %3 %v2int_2_2\n" +
6490 "OpReturn\n" +
6491 "OpFunctionEnd\n",
6492 4, true),
6493 // Test case 17: merge vector imul of snegate
6494 // {2,2} * (-x) = x * {-2,-2}
6495 InstructionFoldingCase<bool>(
6496 Header() +
6497 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
6498 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
6499 "; CHECK: OpConstant [[int]] -2147483648{{[[:space:]]}}\n" +
6500 "; CHECK: [[int_n2:%\\w+]] = OpConstant [[int]] -2{{[[:space:]]}}\n" +
6501 "; CHECK: [[v2int_n2_n2:%\\w+]] = OpConstantComposite [[v2int]] [[int_n2]] [[int_n2]]\n" +
6502 "; CHECK: [[ld:%\\w+]] = OpLoad [[v2int]]\n" +
6503 "; CHECK: %4 = OpIMul [[v2int]] [[ld]] [[v2int_n2_n2]]\n" +
6504 "%main = OpFunction %void None %void_func\n" +
6505 "%main_lab = OpLabel\n" +
6506 "%var = OpVariable %_ptr_v2int Function\n" +
6507 "%2 = OpLoad %v2int %var\n" +
6508 "%3 = OpSNegate %v2int %2\n" +
6509 "%4 = OpIMul %v2int %v2int_2_2 %3\n" +
6510 "OpReturn\n" +
6511 "OpFunctionEnd\n",
6512 4, true),
6513 // Test case 18: Fold OpVectorTimesScalar
6514 // {4,4} = OpVectorTimesScalar v2float {2,2} 2
6515 InstructionFoldingCase<bool>(
6516 Header() +
6517 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6518 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6519 "; CHECK: [[float_4:%\\w+]] = OpConstant [[float]] 4\n" +
6520 "; CHECK: [[v2float_4_4:%\\w+]] = OpConstantComposite [[v2float]] [[float_4]] [[float_4]]\n" +
6521 "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_4_4]]\n" +
6522 "%main = OpFunction %void None %void_func\n" +
6523 "%main_lab = OpLabel\n" +
6524 "%2 = OpVectorTimesScalar %v2float %v2float_2_2 %float_2\n" +
6525 "OpReturn\n" +
6526 "OpFunctionEnd",
6527 2, true),
6528 // Test case 19: Fold OpVectorTimesScalar
6529 // {0,0} = OpVectorTimesScalar v2float v2float_null -1
6530 InstructionFoldingCase<bool>(
6531 Header() +
6532 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6533 "; CHECK: [[v2float:%\\w+]] = OpTypeVector [[float]] 2\n" +
6534 "; CHECK: [[v2float_null:%\\w+]] = OpConstantNull [[v2float]]\n" +
6535 "; CHECK: %2 = OpCopyObject [[v2float]] [[v2float_null]]\n" +
6536 "%main = OpFunction %void None %void_func\n" +
6537 "%main_lab = OpLabel\n" +
6538 "%2 = OpVectorTimesScalar %v2float %v2float_null %float_n1\n" +
6539 "OpReturn\n" +
6540 "OpFunctionEnd",
6541 2, true),
6542 // Test case 20: Fold OpVectorTimesScalar
6543 // {4,4} = OpVectorTimesScalar v2double {2,2} 2
6544 InstructionFoldingCase<bool>(
6545 Header() +
6546 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6547 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6548 "; CHECK: [[double_4:%\\w+]] = OpConstant [[double]] 4\n" +
6549 "; CHECK: [[v2double_4_4:%\\w+]] = OpConstantComposite [[v2double]] [[double_4]] [[double_4]]\n" +
6550 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_4_4]]\n" +
6551 "%main = OpFunction %void None %void_func\n" +
6552 "%main_lab = OpLabel\n" +
6553 "%2 = OpVectorTimesScalar %v2double %v2double_2_2 %double_2\n" +
6554 "OpReturn\n" +
6555 "OpFunctionEnd",
6556 2, true),
6557 // Test case 21: Fold OpVectorTimesScalar
6558 // {0,0} = OpVectorTimesScalar v2double {0,0} n
6559 InstructionFoldingCase<bool>(
6560 Header() +
6561 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6562 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6563 "; CHECK: {{%\\w+}} = OpConstant [[double]] 0\n" +
6564 "; CHECK: [[double_0:%\\w+]] = OpConstant [[double]] 0\n" +
6565 "; CHECK: [[v2double_0_0:%\\w+]] = OpConstantComposite [[v2double]] [[double_0]] [[double_0]]\n" +
6566 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_0_0]]\n" +
6567 "%main = OpFunction %void None %void_func\n" +
6568 "%main_lab = OpLabel\n" +
6569 "%n = OpVariable %_ptr_double Function\n" +
6570 "%load = OpLoad %double %n\n" +
6571 "%2 = OpVectorTimesScalar %v2double %v2double_0_0 %load\n" +
6572 "OpReturn\n" +
6573 "OpFunctionEnd",
6574 2, true),
6575 // Test case 22: Fold OpVectorTimesScalar
6576 // {0,0} = OpVectorTimesScalar v2double n 0
6577 InstructionFoldingCase<bool>(
6578 Header() +
6579 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
6580 "; CHECK: [[v2double:%\\w+]] = OpTypeVector [[double]] 2\n" +
6581 "; CHECK: [[v2double_null:%\\w+]] = OpConstantNull [[v2double]]\n" +
6582 "; CHECK: %2 = OpCopyObject [[v2double]] [[v2double_null]]\n" +
6583 "%main = OpFunction %void None %void_func\n" +
6584 "%main_lab = OpLabel\n" +
6585 "%n = OpVariable %_ptr_v2double Function\n" +
6586 "%load = OpLoad %v2double %n\n" +
6587 "%2 = OpVectorTimesScalar %v2double %load %double_0\n" +
6588 "OpReturn\n" +
6589 "OpFunctionEnd",
6590 2, true),
6591 // Test case 23: merge fmul of fdiv
6592 // x * (y / x) = y
6593 InstructionFoldingCase<bool>(
6594 Header() +
6595 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6596 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6597 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6598 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6599 "%main = OpFunction %void None %void_func\n" +
6600 "%main_lab = OpLabel\n" +
6601 "%x = OpVariable %_ptr_float Function\n" +
6602 "%y = OpVariable %_ptr_float Function\n" +
6603 "%2 = OpLoad %float %x\n" +
6604 "%3 = OpLoad %float %y\n" +
6605 "%4 = OpFDiv %float %3 %2\n" +
6606 "%5 = OpFMul %float %2 %4\n" +
6607 "OpReturn\n" +
6608 "OpFunctionEnd\n",
6609 5, true),
6610 // Test case 24: merge fmul of fdiv
6611 // (y / x) * x = y
6612 InstructionFoldingCase<bool>(
6613 Header() +
6614 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6615 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6616 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6617 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6618 "%main = OpFunction %void None %void_func\n" +
6619 "%main_lab = OpLabel\n" +
6620 "%x = OpVariable %_ptr_float Function\n" +
6621 "%y = OpVariable %_ptr_float Function\n" +
6622 "%2 = OpLoad %float %x\n" +
6623 "%3 = OpLoad %float %y\n" +
6624 "%4 = OpFDiv %float %3 %2\n" +
6625 "%5 = OpFMul %float %4 %2\n" +
6626 "OpReturn\n" +
6627 "OpFunctionEnd\n",
6628 5, true),
6629 // Test case 25: fold overflowing signed 32 bit imuls
6630 // (x * 1073741824) * 2 = x * int_min
6631 InstructionFoldingCase<bool>(
6632 Header() +
6633 "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
6634 "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
6635 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6636 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_min]]\n" +
6637 "%main = OpFunction %void None %void_func\n" +
6638 "%main_lab = OpLabel\n" +
6639 "%var = OpVariable %_ptr_int Function\n" +
6640 "%2 = OpLoad %int %var\n" +
6641 "%3 = OpIMul %int %2 %int_1073741824\n" +
6642 "%4 = OpIMul %int %3 %int_2\n" +
6643 "OpReturn\n" +
6644 "OpFunctionEnd\n",
6645 4, true),
6646 // Test case 26: fold overflowing signed 64 bit imuls
6647 // (x * 4611686018427387904) * 2 = x * long_min
6648 InstructionFoldingCase<bool>(
6649 Header() +
6650 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6651 "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
6652 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6653 "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_min]]\n" +
6654 "%main = OpFunction %void None %void_func\n" +
6655 "%main_lab = OpLabel\n" +
6656 "%var = OpVariable %_ptr_long Function\n" +
6657 "%2 = OpLoad %long %var\n" +
6658 "%3 = OpIMul %long %2 %long_4611686018427387904\n" +
6659 "%4 = OpIMul %long %3 %long_2\n" +
6660 "OpReturn\n" +
6661 "OpFunctionEnd\n",
6662 4, true),
6663 // Test case 27: fold overflowing 32 bit unsigned imuls
6664 // (x * 2147483649) * 2 = x * 2
6665 InstructionFoldingCase<bool>(
6666 Header() +
6667 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
6668 "; CHECK: [[uint_2:%\\w+]] = OpConstant [[uint]] 2\n" +
6669 "; CHECK: [[ld:%\\w+]] = OpLoad [[uint]]\n" +
6670 "; CHECK: %4 = OpIMul [[uint]] [[ld]] [[uint_2]]\n" +
6671 "%main = OpFunction %void None %void_func\n" +
6672 "%main_lab = OpLabel\n" +
6673 "%var = OpVariable %_ptr_uint Function\n" +
6674 "%2 = OpLoad %uint %var\n" +
6675 "%3 = OpIMul %uint %2 %uint_2147483649\n" +
6676 "%4 = OpIMul %uint %3 %uint_2\n" +
6677 "OpReturn\n" +
6678 "OpFunctionEnd\n",
6679 4, true),
6680 // Test case 28: fold overflowing 64 bit unsigned imuls
6681 // (x * 9223372036854775809) * 2 = x * 2
6682 InstructionFoldingCase<bool>(
6683 Header() +
6684 "; CHECK: [[ulong:%\\w+]] = OpTypeInt 64 0\n" +
6685 "; CHECK: [[ulong_2:%\\w+]] = OpConstant [[ulong]] 2\n" +
6686 "; CHECK: [[ld:%\\w+]] = OpLoad [[ulong]]\n" +
6687 "; CHECK: %4 = OpIMul [[ulong]] [[ld]] [[ulong_2]]\n" +
6688 "%main = OpFunction %void None %void_func\n" +
6689 "%main_lab = OpLabel\n" +
6690 "%var = OpVariable %_ptr_ulong Function\n" +
6691 "%2 = OpLoad %ulong %var\n" +
6692 "%3 = OpIMul %ulong %2 %ulong_9223372036854775809\n" +
6693 "%4 = OpIMul %ulong %3 %ulong_2\n" +
6694 "OpReturn\n" +
6695 "OpFunctionEnd\n",
6696 4, true),
6697 // Test case 29: fold underflowing signed 32 bit imuls
6698 // (x * (-858993459)) * 10 = x * 2
6699 InstructionFoldingCase<bool>(
6700 Header() +
6701 "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
6702 "; CHECK: [[int_2:%\\w+]] = OpConstant [[int]] 2\n" +
6703 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
6704 "; CHECK: %4 = OpIMul [[int]] [[ld]] [[int_2]]\n" +
6705 "%main = OpFunction %void None %void_func\n" +
6706 "%main_lab = OpLabel\n" +
6707 "%var = OpVariable %_ptr_int Function\n" +
6708 "%2 = OpLoad %int %var\n" +
6709 "%3 = OpIMul %int %2 %int_n858993459\n" +
6710 "%4 = OpIMul %int %3 %int_10\n" +
6711 "OpReturn\n" +
6712 "OpFunctionEnd\n",
6713 4, true),
6714 // Test case 30: fold underflowing signed 64 bit imuls
6715 // (x * (-3689348814741910323)) * 10 = x * 2
6716 InstructionFoldingCase<bool>(
6717 Header() +
6718 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
6719 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
6720 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
6721 "; CHECK: %4 = OpIMul [[long]] [[ld]] [[long_2]]\n" +
6722 "%main = OpFunction %void None %void_func\n" +
6723 "%main_lab = OpLabel\n" +
6724 "%var = OpVariable %_ptr_long Function\n" +
6725 "%2 = OpLoad %long %var\n" +
6726 "%3 = OpIMul %long %2 %long_n3689348814741910323\n" +
6727 "%4 = OpIMul %long %3 %long_10\n" +
6728 "OpReturn\n" +
6729 "OpFunctionEnd\n",
6730 4, true)
6731 ));
6732
6733 INSTANTIATE_TEST_SUITE_P(MergeDivTest, MatchingInstructionFoldingTest,
6734 ::testing::Values(
6735 // Test case 0: merge consecutive fdiv
6736 // 4.0 / (2.0 / x) = 2.0 * x
6737 InstructionFoldingCase<bool>(
6738 Header() +
6739 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6740 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6741 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6742 "; CHECK: %4 = OpFMul [[float]] [[float_2]] [[ld]]\n" +
6743 "%main = OpFunction %void None %void_func\n" +
6744 "%main_lab = OpLabel\n" +
6745 "%var = OpVariable %_ptr_float Function\n" +
6746 "%2 = OpLoad %float %var\n" +
6747 "%3 = OpFDiv %float %float_2 %2\n" +
6748 "%4 = OpFDiv %float %float_4 %3\n" +
6749 "OpReturn\n" +
6750 "OpFunctionEnd\n",
6751 4, true),
6752 // Test case 1: merge consecutive fdiv
6753 // 4.0 / (x / 2.0) = 8.0 / x
6754 InstructionFoldingCase<bool>(
6755 Header() +
6756 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6757 "; CHECK: [[float_8:%\\w+]] = OpConstant [[float]] 8\n" +
6758 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6759 "; CHECK: %4 = OpFDiv [[float]] [[float_8]] [[ld]]\n" +
6760 "%main = OpFunction %void None %void_func\n" +
6761 "%main_lab = OpLabel\n" +
6762 "%var = OpVariable %_ptr_float Function\n" +
6763 "%2 = OpLoad %float %var\n" +
6764 "%3 = OpFDiv %float %2 %float_2\n" +
6765 "%4 = OpFDiv %float %float_4 %3\n" +
6766 "OpReturn\n" +
6767 "OpFunctionEnd\n",
6768 4, true),
6769 // Test case 2: merge consecutive fdiv
6770 // (4.0 / x) / 2.0 = 2.0 / x
6771 InstructionFoldingCase<bool>(
6772 Header() +
6773 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6774 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
6775 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
6776 "; CHECK: %4 = OpFDiv [[float]] [[float_2]] [[ld]]\n" +
6777 "%main = OpFunction %void None %void_func\n" +
6778 "%main_lab = OpLabel\n" +
6779 "%var = OpVariable %_ptr_float Function\n" +
6780 "%2 = OpLoad %float %var\n" +
6781 "%3 = OpFDiv %float %float_4 %2\n" +
6782 "%4 = OpFDiv %float %3 %float_2\n" +
6783 "OpReturn\n" +
6784 "OpFunctionEnd\n",
6785 4, true),
6786 // Test case 3: Do not merge consecutive sdiv
6787 // 4 / (2 / x)
6788 InstructionFoldingCase<bool>(
6789 Header() +
6790 "%main = OpFunction %void None %void_func\n" +
6791 "%main_lab = OpLabel\n" +
6792 "%var = OpVariable %_ptr_int Function\n" +
6793 "%2 = OpLoad %int %var\n" +
6794 "%3 = OpSDiv %int %int_2 %2\n" +
6795 "%4 = OpSDiv %int %int_4 %3\n" +
6796 "OpReturn\n" +
6797 "OpFunctionEnd\n",
6798 4, false),
6799 // Test case 4: Do not merge consecutive sdiv
6800 // 4 / (x / 2)
6801 InstructionFoldingCase<bool>(
6802 Header() +
6803 "%main = OpFunction %void None %void_func\n" +
6804 "%main_lab = OpLabel\n" +
6805 "%var = OpVariable %_ptr_int Function\n" +
6806 "%2 = OpLoad %int %var\n" +
6807 "%3 = OpSDiv %int %2 %int_2\n" +
6808 "%4 = OpSDiv %int %int_4 %3\n" +
6809 "OpReturn\n" +
6810 "OpFunctionEnd\n",
6811 4, false),
6812 // Test case 5: Do not merge consecutive sdiv
6813 // (4 / x) / 2
6814 InstructionFoldingCase<bool>(
6815 Header() +
6816 "%main = OpFunction %void None %void_func\n" +
6817 "%main_lab = OpLabel\n" +
6818 "%var = OpVariable %_ptr_int Function\n" +
6819 "%2 = OpLoad %int %var\n" +
6820 "%3 = OpSDiv %int %int_4 %2\n" +
6821 "%4 = OpSDiv %int %3 %int_2\n" +
6822 "OpReturn\n" +
6823 "OpFunctionEnd\n",
6824 4, false),
6825 // Test case 6: Do not merge consecutive sdiv
6826 // (x / 4) / 2
6827 InstructionFoldingCase<bool>(
6828 Header() +
6829 "%main = OpFunction %void None %void_func\n" +
6830 "%main_lab = OpLabel\n" +
6831 "%var = OpVariable %_ptr_int Function\n" +
6832 "%2 = OpLoad %int %var\n" +
6833 "%3 = OpSDiv %int %2 %int_4\n" +
6834 "%4 = OpSDiv %int %3 %int_2\n" +
6835 "OpReturn\n" +
6836 "OpFunctionEnd\n",
6837 4, false),
6838 // Test case 7: Do not merge sdiv of imul
6839 // 4 / (2 * x)
6840 InstructionFoldingCase<bool>(
6841 Header() +
6842 "%main = OpFunction %void None %void_func\n" +
6843 "%main_lab = OpLabel\n" +
6844 "%var = OpVariable %_ptr_int Function\n" +
6845 "%2 = OpLoad %int %var\n" +
6846 "%3 = OpIMul %int %int_2 %2\n" +
6847 "%4 = OpSDiv %int %int_4 %3\n" +
6848 "OpReturn\n" +
6849 "OpFunctionEnd\n",
6850 4, false),
6851 // Test case 8: Do not merge sdiv of imul
6852 // 4 / (x * 2)
6853 InstructionFoldingCase<bool>(
6854 Header() +
6855 "%main = OpFunction %void None %void_func\n" +
6856 "%main_lab = OpLabel\n" +
6857 "%var = OpVariable %_ptr_int Function\n" +
6858 "%2 = OpLoad %int %var\n" +
6859 "%3 = OpIMul %int %2 %int_2\n" +
6860 "%4 = OpSDiv %int %int_4 %3\n" +
6861 "OpReturn\n" +
6862 "OpFunctionEnd\n",
6863 4, false),
6864 // Test case 9: Do not merge sdiv of imul
6865 // (4 * x) / 2
6866 InstructionFoldingCase<bool>(
6867 Header() +
6868 "%main = OpFunction %void None %void_func\n" +
6869 "%main_lab = OpLabel\n" +
6870 "%var = OpVariable %_ptr_int Function\n" +
6871 "%2 = OpLoad %int %var\n" +
6872 "%3 = OpIMul %int %int_4 %2\n" +
6873 "%4 = OpSDiv %int %3 %int_2\n" +
6874 "OpReturn\n" +
6875 "OpFunctionEnd\n",
6876 4, false),
6877 // Test case 10: Do not merge sdiv of imul
6878 // (x * 4) / 2
6879 InstructionFoldingCase<bool>(
6880 Header() +
6881 "%main = OpFunction %void None %void_func\n" +
6882 "%main_lab = OpLabel\n" +
6883 "%var = OpVariable %_ptr_int Function\n" +
6884 "%2 = OpLoad %int %var\n" +
6885 "%3 = OpIMul %int %2 %int_4\n" +
6886 "%4 = OpSDiv %int %3 %int_2\n" +
6887 "OpReturn\n" +
6888 "OpFunctionEnd\n",
6889 4, false),
6890 // Test case 11: Do not merge sdiv of snegate. If %2 is INT_MIN, then the
6891 // sign of %3 will be the same as %2. This cannot be accounted for in OpSDiv.
6892 // Specifically, (-INT_MIN) / 2 != INT_MIN / -2.
6893 InstructionFoldingCase<bool>(
6894 Header() +
6895 "%main = OpFunction %void None %void_func\n" +
6896 "%main_lab = OpLabel\n" +
6897 "%var = OpVariable %_ptr_int Function\n" +
6898 "%2 = OpLoad %int %var\n" +
6899 "%3 = OpSNegate %int %2\n" +
6900 "%4 = OpSDiv %int %3 %int_2\n" +
6901 "OpReturn\n" +
6902 "OpFunctionEnd\n",
6903 4, false),
6904 // Test case 12: Do not merge sdiv of snegate. If %2 is INT_MIN, then the
6905 // sign of %3 will be the same as %2. This cannot be accounted for in OpSDiv.
6906 // Specifically, 2 / (-INT_MIN) != -2 / INT_MIN.
6907 InstructionFoldingCase<bool>(
6908 Header() +
6909 "%main = OpFunction %void None %void_func\n" +
6910 "%main_lab = OpLabel\n" +
6911 "%var = OpVariable %_ptr_int Function\n" +
6912 "%2 = OpLoad %int %var\n" +
6913 "%3 = OpSNegate %int %2\n" +
6914 "%4 = OpSDiv %int %int_2 %3\n" +
6915 "OpReturn\n" +
6916 "OpFunctionEnd\n",
6917 4, false),
6918 // Test case 13: Don't merge
6919 // (x / {null}) / {null}
6920 InstructionFoldingCase<bool>(
6921 Header() +
6922 "%main = OpFunction %void None %void_func\n" +
6923 "%main_lab = OpLabel\n" +
6924 "%var = OpVariable %_ptr_v2float Function\n" +
6925 "%2 = OpLoad %float %var\n" +
6926 "%3 = OpFDiv %float %2 %v2float_null\n" +
6927 "%4 = OpFDiv %float %3 %v2float_null\n" +
6928 "OpReturn\n" +
6929 "OpFunctionEnd\n",
6930 4, false),
6931 // Test case 14: merge fmul of fdiv
6932 // (y * x) / x = y
6933 InstructionFoldingCase<bool>(
6934 Header() +
6935 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6936 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6937 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6938 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6939 "%main = OpFunction %void None %void_func\n" +
6940 "%main_lab = OpLabel\n" +
6941 "%x = OpVariable %_ptr_float Function\n" +
6942 "%y = OpVariable %_ptr_float Function\n" +
6943 "%2 = OpLoad %float %x\n" +
6944 "%3 = OpLoad %float %y\n" +
6945 "%4 = OpFMul %float %3 %2\n" +
6946 "%5 = OpFDiv %float %4 %2\n" +
6947 "OpReturn\n" +
6948 "OpFunctionEnd\n",
6949 5, true),
6950 // Test case 15: merge fmul of fdiv
6951 // (x * y) / x = y
6952 InstructionFoldingCase<bool>(
6953 Header() +
6954 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
6955 "; CHECK: [[ldx:%\\w+]] = OpLoad [[float]]\n" +
6956 "; CHECK: [[ldy:%\\w+]] = OpLoad [[float]] [[y:%\\w+]]\n" +
6957 "; CHECK: %5 = OpCopyObject [[float]] [[ldy]]\n" +
6958 "%main = OpFunction %void None %void_func\n" +
6959 "%main_lab = OpLabel\n" +
6960 "%x = OpVariable %_ptr_float Function\n" +
6961 "%y = OpVariable %_ptr_float Function\n" +
6962 "%2 = OpLoad %float %x\n" +
6963 "%3 = OpLoad %float %y\n" +
6964 "%4 = OpFMul %float %2 %3\n" +
6965 "%5 = OpFDiv %float %4 %2\n" +
6966 "OpReturn\n" +
6967 "OpFunctionEnd\n",
6968 5, true),
6969 // Test case 16: Do not merge udiv of snegate
6970 // (-x) / 2u
6971 InstructionFoldingCase<bool>(
6972 Header() +
6973 "%main = OpFunction %void None %void_func\n" +
6974 "%main_lab = OpLabel\n" +
6975 "%var = OpVariable %_ptr_uint Function\n" +
6976 "%2 = OpLoad %uint %var\n" +
6977 "%3 = OpSNegate %uint %2\n" +
6978 "%4 = OpUDiv %uint %3 %uint_2\n" +
6979 "OpReturn\n" +
6980 "OpFunctionEnd\n",
6981 4, false),
6982 // Test case 17: Do not merge udiv of snegate
6983 // 2u / (-x)
6984 InstructionFoldingCase<bool>(
6985 Header() +
6986 "%main = OpFunction %void None %void_func\n" +
6987 "%main_lab = OpLabel\n" +
6988 "%var = OpVariable %_ptr_uint Function\n" +
6989 "%2 = OpLoad %uint %var\n" +
6990 "%3 = OpSNegate %uint %2\n" +
6991 "%4 = OpUDiv %uint %uint_2 %3\n" +
6992 "OpReturn\n" +
6993 "OpFunctionEnd\n",
6994 4, false)
6995 ));
6996
6997 INSTANTIATE_TEST_SUITE_P(MergeAddTest, MatchingInstructionFoldingTest,
6998 ::testing::Values(
6999 // Test case 0: merge add of negate
7000 // (-x) + 2 = 2 - x
7001 InstructionFoldingCase<bool>(
7002 Header() +
7003 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7004 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
7005 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7006 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
7007 "%main = OpFunction %void None %void_func\n" +
7008 "%main_lab = OpLabel\n" +
7009 "%var = OpVariable %_ptr_float Function\n" +
7010 "%2 = OpLoad %float %var\n" +
7011 "%3 = OpFNegate %float %2\n" +
7012 "%4 = OpFAdd %float %3 %float_2\n" +
7013 "OpReturn\n" +
7014 "OpFunctionEnd\n",
7015 4, true),
7016 // Test case 1: merge add of negate
7017 // 2 + (-x) = 2 - x
7018 InstructionFoldingCase<bool>(
7019 Header() +
7020 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7021 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
7022 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7023 "; CHECK: %4 = OpFSub [[float]] [[float_2]] [[ld]]\n" +
7024 "%main = OpFunction %void None %void_func\n" +
7025 "%main_lab = OpLabel\n" +
7026 "%var = OpVariable %_ptr_float Function\n" +
7027 "%2 = OpLoad %float %var\n" +
7028 "%3 = OpSNegate %float %2\n" +
7029 "%4 = OpIAdd %float %float_2 %3\n" +
7030 "OpReturn\n" +
7031 "OpFunctionEnd\n",
7032 4, true),
7033 // Test case 2: merge add of negate
7034 // (-x) + 2 = 2 - x
7035 InstructionFoldingCase<bool>(
7036 Header() +
7037 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
7038 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
7039 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7040 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
7041 "%main = OpFunction %void None %void_func\n" +
7042 "%main_lab = OpLabel\n" +
7043 "%var = OpVariable %_ptr_long Function\n" +
7044 "%2 = OpLoad %long %var\n" +
7045 "%3 = OpSNegate %long %2\n" +
7046 "%4 = OpIAdd %long %3 %long_2\n" +
7047 "OpReturn\n" +
7048 "OpFunctionEnd\n",
7049 4, true),
7050 // Test case 3: merge add of negate
7051 // 2 + (-x) = 2 - x
7052 InstructionFoldingCase<bool>(
7053 Header() +
7054 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
7055 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
7056 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7057 "; CHECK: %4 = OpISub [[long]] [[long_2]] [[ld]]\n" +
7058 "%main = OpFunction %void None %void_func\n" +
7059 "%main_lab = OpLabel\n" +
7060 "%var = OpVariable %_ptr_long Function\n" +
7061 "%2 = OpLoad %long %var\n" +
7062 "%3 = OpSNegate %long %2\n" +
7063 "%4 = OpIAdd %long %long_2 %3\n" +
7064 "OpReturn\n" +
7065 "OpFunctionEnd\n",
7066 4, true),
7067 // Test case 4: merge add of subtract
7068 // (x - 1) + 2 = x + 1
7069 InstructionFoldingCase<bool>(
7070 Header() +
7071 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7072 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7073 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7074 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7075 "%main = OpFunction %void None %void_func\n" +
7076 "%main_lab = OpLabel\n" +
7077 "%var = OpVariable %_ptr_float Function\n" +
7078 "%2 = OpLoad %float %var\n" +
7079 "%3 = OpFSub %float %2 %float_1\n" +
7080 "%4 = OpFAdd %float %3 %float_2\n" +
7081 "OpReturn\n" +
7082 "OpFunctionEnd\n",
7083 4, true),
7084 // Test case 5: merge add of subtract
7085 // (1 - x) + 2 = 3 - x
7086 InstructionFoldingCase<bool>(
7087 Header() +
7088 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7089 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7090 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7091 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
7092 "%main = OpFunction %void None %void_func\n" +
7093 "%main_lab = OpLabel\n" +
7094 "%var = OpVariable %_ptr_float Function\n" +
7095 "%2 = OpLoad %float %var\n" +
7096 "%3 = OpFSub %float %float_1 %2\n" +
7097 "%4 = OpFAdd %float %3 %float_2\n" +
7098 "OpReturn\n" +
7099 "OpFunctionEnd\n",
7100 4, true),
7101 // Test case 6: merge add of subtract
7102 // 2 + (x - 1) = x + 1
7103 InstructionFoldingCase<bool>(
7104 Header() +
7105 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7106 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7107 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7108 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7109 "%main = OpFunction %void None %void_func\n" +
7110 "%main_lab = OpLabel\n" +
7111 "%var = OpVariable %_ptr_float Function\n" +
7112 "%2 = OpLoad %float %var\n" +
7113 "%3 = OpFSub %float %2 %float_1\n" +
7114 "%4 = OpFAdd %float %float_2 %3\n" +
7115 "OpReturn\n" +
7116 "OpFunctionEnd\n",
7117 4, true),
7118 // Test case 7: merge add of subtract
7119 // 2 + (1 - x) = 3 - x
7120 InstructionFoldingCase<bool>(
7121 Header() +
7122 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7123 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7124 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7125 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
7126 "%main = OpFunction %void None %void_func\n" +
7127 "%main_lab = OpLabel\n" +
7128 "%var = OpVariable %_ptr_float Function\n" +
7129 "%2 = OpLoad %float %var\n" +
7130 "%3 = OpFSub %float %float_1 %2\n" +
7131 "%4 = OpFAdd %float %float_2 %3\n" +
7132 "OpReturn\n" +
7133 "OpFunctionEnd\n",
7134 4, true),
7135 // Test case 8: merge add of add
7136 // (x + 1) + 2 = x + 3
7137 InstructionFoldingCase<bool>(
7138 Header() +
7139 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7140 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7141 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7142 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
7143 "%main = OpFunction %void None %void_func\n" +
7144 "%main_lab = OpLabel\n" +
7145 "%var = OpVariable %_ptr_float Function\n" +
7146 "%2 = OpLoad %float %var\n" +
7147 "%3 = OpFAdd %float %2 %float_1\n" +
7148 "%4 = OpFAdd %float %3 %float_2\n" +
7149 "OpReturn\n" +
7150 "OpFunctionEnd\n",
7151 4, true),
7152 // Test case 9: merge add of add
7153 // (1 + x) + 2 = 3 + x
7154 InstructionFoldingCase<bool>(
7155 Header() +
7156 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7157 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7158 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7159 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
7160 "%main = OpFunction %void None %void_func\n" +
7161 "%main_lab = OpLabel\n" +
7162 "%var = OpVariable %_ptr_float Function\n" +
7163 "%2 = OpLoad %float %var\n" +
7164 "%3 = OpFAdd %float %float_1 %2\n" +
7165 "%4 = OpFAdd %float %3 %float_2\n" +
7166 "OpReturn\n" +
7167 "OpFunctionEnd\n",
7168 4, true),
7169 // Test case 10: merge add of add
7170 // 2 + (x + 1) = x + 1
7171 InstructionFoldingCase<bool>(
7172 Header() +
7173 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7174 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7175 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7176 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
7177 "%main = OpFunction %void None %void_func\n" +
7178 "%main_lab = OpLabel\n" +
7179 "%var = OpVariable %_ptr_float Function\n" +
7180 "%2 = OpLoad %float %var\n" +
7181 "%3 = OpFAdd %float %2 %float_1\n" +
7182 "%4 = OpFAdd %float %float_2 %3\n" +
7183 "OpReturn\n" +
7184 "OpFunctionEnd\n",
7185 4, true),
7186 // Test case 11: merge add of add
7187 // 2 + (1 + x) = 3 - x
7188 InstructionFoldingCase<bool>(
7189 Header() +
7190 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7191 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7192 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7193 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_3]]\n" +
7194 "%main = OpFunction %void None %void_func\n" +
7195 "%main_lab = OpLabel\n" +
7196 "%var = OpVariable %_ptr_float Function\n" +
7197 "%2 = OpLoad %float %var\n" +
7198 "%3 = OpFAdd %float %float_1 %2\n" +
7199 "%4 = OpFAdd %float %float_2 %3\n" +
7200 "OpReturn\n" +
7201 "OpFunctionEnd\n",
7202 4, true),
7203 // Test case 12: fold overflowing signed 32 bit iadds
7204 // (x + int_max) + 1 = x + int_min
7205 InstructionFoldingCase<bool>(
7206 Header() +
7207 "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
7208 "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
7209 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
7210 "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_min]]\n" +
7211 "%main = OpFunction %void None %void_func\n" +
7212 "%main_lab = OpLabel\n" +
7213 "%var = OpVariable %_ptr_int Function\n" +
7214 "%2 = OpLoad %int %var\n" +
7215 "%3 = OpIAdd %int %2 %int_max\n" +
7216 "%4 = OpIAdd %int %3 %int_1\n" +
7217 "OpReturn\n" +
7218 "OpFunctionEnd\n",
7219 4, true),
7220 // Test case 13: fold overflowing signed 64 bit iadds
7221 // (x + long_max) + 1 = x + long_min
7222 InstructionFoldingCase<bool>(
7223 Header() +
7224 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
7225 "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
7226 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7227 "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_min]]\n" +
7228 "%main = OpFunction %void None %void_func\n" +
7229 "%main_lab = OpLabel\n" +
7230 "%var = OpVariable %_ptr_long Function\n" +
7231 "%2 = OpLoad %long %var\n" +
7232 "%3 = OpIAdd %long %2 %long_max\n" +
7233 "%4 = OpIAdd %long %3 %long_1\n" +
7234 "OpReturn\n" +
7235 "OpFunctionEnd\n",
7236 4, true),
7237 // Test case 14: fold overflowing 32 bit unsigned iadds
7238 // (x + uint_max) + 2 = x + 1
7239 InstructionFoldingCase<bool>(
7240 Header() +
7241 "; CHECK: [[uint:%\\w+]] = OpTypeInt 32 0\n" +
7242 "; CHECK: [[uint_1:%\\w+]] = OpConstant [[uint]] 1\n" +
7243 "; CHECK: [[ld:%\\w+]] = OpLoad [[uint]]\n" +
7244 "; CHECK: %4 = OpIAdd [[uint]] [[ld]] [[uint_1]]\n" +
7245 "%main = OpFunction %void None %void_func\n" +
7246 "%main_lab = OpLabel\n" +
7247 "%var = OpVariable %_ptr_uint Function\n" +
7248 "%2 = OpLoad %uint %var\n" +
7249 "%3 = OpIAdd %uint %2 %uint_max\n" +
7250 "%4 = OpIAdd %uint %3 %uint_2\n" +
7251 "OpReturn\n" +
7252 "OpFunctionEnd\n",
7253 4, true),
7254 // Test case 15: fold overflowing 64 bit unsigned iadds
7255 // (x + ulong_max) + 2 = x + 1
7256 InstructionFoldingCase<bool>(
7257 Header() +
7258 "; CHECK: [[ulong:%\\w+]] = OpTypeInt 64 0\n" +
7259 "; CHECK: [[ulong_1:%\\w+]] = OpConstant [[ulong]] 1\n" +
7260 "; CHECK: [[ld:%\\w+]] = OpLoad [[ulong]]\n" +
7261 "; CHECK: %4 = OpIAdd [[ulong]] [[ld]] [[ulong_1]]\n" +
7262 "%main = OpFunction %void None %void_func\n" +
7263 "%main_lab = OpLabel\n" +
7264 "%var = OpVariable %_ptr_ulong Function\n" +
7265 "%2 = OpLoad %ulong %var\n" +
7266 "%3 = OpIAdd %ulong %2 %ulong_max\n" +
7267 "%4 = OpIAdd %ulong %3 %ulong_2\n" +
7268 "OpReturn\n" +
7269 "OpFunctionEnd\n",
7270 4, true),
7271 // Test case 16: fold underflowing signed 32 bit iadds
7272 // (x + int_min) + (-1) = x + int_max
7273 InstructionFoldingCase<bool>(
7274 Header() +
7275 "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
7276 "; CHECK: [[int_max:%\\w+]] = OpConstant [[int]] 2147483647\n" +
7277 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
7278 "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_max]]\n" +
7279 "%main = OpFunction %void None %void_func\n" +
7280 "%main_lab = OpLabel\n" +
7281 "%var = OpVariable %_ptr_int Function\n" +
7282 "%2 = OpLoad %int %var\n" +
7283 "%3 = OpIAdd %int %2 %int_min\n" +
7284 "%4 = OpIAdd %int %3 %int_n1\n" +
7285 "OpReturn\n" +
7286 "OpFunctionEnd\n",
7287 4, true),
7288 // Test case 17: fold underflowing signed 64 bit iadds
7289 // (x + long_min) + (-1) = x + long_max
7290 InstructionFoldingCase<bool>(
7291 Header() +
7292 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
7293 "; CHECK: [[long_max:%\\w+]] = OpConstant [[long]] 9223372036854775807\n" +
7294 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7295 "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_max]]\n" +
7296 "%main = OpFunction %void None %void_func\n" +
7297 "%main_lab = OpLabel\n" +
7298 "%var = OpVariable %_ptr_long Function\n" +
7299 "%2 = OpLoad %long %var\n" +
7300 "%3 = OpIAdd %long %2 %long_min\n" +
7301 "%4 = OpIAdd %long %3 %long_n1\n" +
7302 "OpReturn\n" +
7303 "OpFunctionEnd\n",
7304 4, true)
7305 ));
7306
7307 INSTANTIATE_TEST_SUITE_P(MergeGenericAddSub, MatchingInstructionFoldingTest,
7308 ::testing::Values(
7309 // Test case 0: merge of add of sub
7310 // (a - b) + b => a
7311 InstructionFoldingCase<bool>(
7312 Header() +
7313 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7314 "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
7315 "%main = OpFunction %void None %void_func\n" +
7316 "%main_lab = OpLabel\n" +
7317 "%var0 = OpVariable %_ptr_float Function\n" +
7318 "%var1 = OpVariable %_ptr_float Function\n" +
7319 "%3 = OpLoad %float %var0\n" +
7320 "%4 = OpLoad %float %var1\n" +
7321 "%5 = OpFSub %float %3 %4\n" +
7322 "%6 = OpFAdd %float %5 %4\n" +
7323 "OpReturn\n" +
7324 "OpFunctionEnd\n",
7325 6, true),
7326 // Test case 1: merge of add of sub
7327 // b + (a - b) => a
7328 InstructionFoldingCase<bool>(
7329 Header() +
7330 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7331 "; CHECK: %6 = OpCopyObject [[float]] %3\n" +
7332 "%main = OpFunction %void None %void_func\n" +
7333 "%main_lab = OpLabel\n" +
7334 "%var0 = OpVariable %_ptr_float Function\n" +
7335 "%var1 = OpVariable %_ptr_float Function\n" +
7336 "%3 = OpLoad %float %var0\n" +
7337 "%4 = OpLoad %float %var1\n" +
7338 "%5 = OpFSub %float %3 %4\n" +
7339 "%6 = OpFAdd %float %4 %5\n" +
7340 "OpReturn\n" +
7341 "OpFunctionEnd\n",
7342 6, true)
7343 ));
7344
7345 INSTANTIATE_TEST_SUITE_P(FactorAddMul, MatchingInstructionFoldingTest,
7346 ::testing::Values(
7347 // Test case 0: factor of add of muls
7348 // (a * b) + (a * c) => a * (b + c)
7349 InstructionFoldingCase<bool>(
7350 Header() +
7351 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7352 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7353 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7354 "%main = OpFunction %void None %void_func\n" +
7355 "%main_lab = OpLabel\n" +
7356 "%var0 = OpVariable %_ptr_float Function\n" +
7357 "%var1 = OpVariable %_ptr_float Function\n" +
7358 "%var2 = OpVariable %_ptr_float Function\n" +
7359 "%4 = OpLoad %float %var0\n" +
7360 "%5 = OpLoad %float %var1\n" +
7361 "%6 = OpLoad %float %var2\n" +
7362 "%7 = OpFMul %float %6 %4\n" +
7363 "%8 = OpFMul %float %6 %5\n" +
7364 "%9 = OpFAdd %float %7 %8\n" +
7365 "OpReturn\n" +
7366 "OpFunctionEnd\n",
7367 9, true),
7368 // Test case 1: factor of add of muls
7369 // (b * a) + (a * c) => a * (b + c)
7370 InstructionFoldingCase<bool>(
7371 Header() +
7372 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7373 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7374 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7375 "%main = OpFunction %void None %void_func\n" +
7376 "%main_lab = OpLabel\n" +
7377 "%var0 = OpVariable %_ptr_float Function\n" +
7378 "%var1 = OpVariable %_ptr_float Function\n" +
7379 "%var2 = OpVariable %_ptr_float Function\n" +
7380 "%4 = OpLoad %float %var0\n" +
7381 "%5 = OpLoad %float %var1\n" +
7382 "%6 = OpLoad %float %var2\n" +
7383 "%7 = OpFMul %float %4 %6\n" +
7384 "%8 = OpFMul %float %6 %5\n" +
7385 "%9 = OpFAdd %float %7 %8\n" +
7386 "OpReturn\n" +
7387 "OpFunctionEnd\n",
7388 9, true),
7389 // Test case 2: factor of add of muls
7390 // (a * b) + (c * a) => a * (b + c)
7391 InstructionFoldingCase<bool>(
7392 Header() +
7393 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7394 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7395 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7396 "%main = OpFunction %void None %void_func\n" +
7397 "%main_lab = OpLabel\n" +
7398 "%var0 = OpVariable %_ptr_float Function\n" +
7399 "%var1 = OpVariable %_ptr_float Function\n" +
7400 "%var2 = OpVariable %_ptr_float Function\n" +
7401 "%4 = OpLoad %float %var0\n" +
7402 "%5 = OpLoad %float %var1\n" +
7403 "%6 = OpLoad %float %var2\n" +
7404 "%7 = OpFMul %float %6 %4\n" +
7405 "%8 = OpFMul %float %5 %6\n" +
7406 "%9 = OpFAdd %float %7 %8\n" +
7407 "OpReturn\n" +
7408 "OpFunctionEnd\n",
7409 9, true),
7410 // Test case 3: factor of add of muls
7411 // (b * a) + (c * a) => a * (b + c)
7412 InstructionFoldingCase<bool>(
7413 Header() +
7414 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7415 "; CHECK: [[newadd:%\\w+]] = OpFAdd [[float]] %4 %5\n" +
7416 "; CHECK: %9 = OpFMul [[float]] %6 [[newadd]]\n" +
7417 "%main = OpFunction %void None %void_func\n" +
7418 "%main_lab = OpLabel\n" +
7419 "%var0 = OpVariable %_ptr_float Function\n" +
7420 "%var1 = OpVariable %_ptr_float Function\n" +
7421 "%var2 = OpVariable %_ptr_float Function\n" +
7422 "%4 = OpLoad %float %var0\n" +
7423 "%5 = OpLoad %float %var1\n" +
7424 "%6 = OpLoad %float %var2\n" +
7425 "%7 = OpFMul %float %4 %6\n" +
7426 "%8 = OpFMul %float %5 %6\n" +
7427 "%9 = OpFAdd %float %7 %8\n" +
7428 "OpReturn\n" +
7429 "OpFunctionEnd\n",
7430 9, true)
7431 ));
7432
7433 INSTANTIATE_TEST_SUITE_P(MergeSubTest, MatchingInstructionFoldingTest,
7434 ::testing::Values(
7435 // Test case 0: merge sub of negate
7436 // (-x) - 2 = -2 - x
7437 InstructionFoldingCase<bool>(
7438 Header() +
7439 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7440 "; CHECK: [[float_n2:%\\w+]] = OpConstant [[float]] -2{{[[:space:]]}}\n" +
7441 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7442 "; CHECK: %4 = OpFSub [[float]] [[float_n2]] [[ld]]\n" +
7443 "%main = OpFunction %void None %void_func\n" +
7444 "%main_lab = OpLabel\n" +
7445 "%var = OpVariable %_ptr_float Function\n" +
7446 "%2 = OpLoad %float %var\n" +
7447 "%3 = OpFNegate %float %2\n" +
7448 "%4 = OpFSub %float %3 %float_2\n" +
7449 "OpReturn\n" +
7450 "OpFunctionEnd\n",
7451 4, true),
7452 // Test case 1: merge sub of negate
7453 // 2 - (-x) = x + 2
7454 InstructionFoldingCase<bool>(
7455 Header() +
7456 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7457 "; CHECK: [[float_2:%\\w+]] = OpConstant [[float]] 2\n" +
7458 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7459 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_2]]\n" +
7460 "%main = OpFunction %void None %void_func\n" +
7461 "%main_lab = OpLabel\n" +
7462 "%var = OpVariable %_ptr_float Function\n" +
7463 "%2 = OpLoad %float %var\n" +
7464 "%3 = OpFNegate %float %2\n" +
7465 "%4 = OpFSub %float %float_2 %3\n" +
7466 "OpReturn\n" +
7467 "OpFunctionEnd\n",
7468 4, true),
7469 // Test case 2: merge sub of negate
7470 // (-x) - 2 = -2 - x
7471 InstructionFoldingCase<bool>(
7472 Header() +
7473 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
7474 "; CHECK: [[long_n2:%\\w+]] = OpConstant [[long]] -2{{[[:space:]]}}\n" +
7475 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7476 "; CHECK: %4 = OpISub [[long]] [[long_n2]] [[ld]]\n" +
7477 "%main = OpFunction %void None %void_func\n" +
7478 "%main_lab = OpLabel\n" +
7479 "%var = OpVariable %_ptr_long Function\n" +
7480 "%2 = OpLoad %long %var\n" +
7481 "%3 = OpSNegate %long %2\n" +
7482 "%4 = OpISub %long %3 %long_2\n" +
7483 "OpReturn\n" +
7484 "OpFunctionEnd\n",
7485 4, true),
7486 // Test case 3: merge sub of negate
7487 // 2 - (-x) = x + 2
7488 InstructionFoldingCase<bool>(
7489 Header() +
7490 "; CHECK: [[long:%\\w+]] = OpTypeInt 64 1\n" +
7491 "; CHECK: [[long_2:%\\w+]] = OpConstant [[long]] 2\n" +
7492 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7493 "; CHECK: %4 = OpIAdd [[long]] [[ld]] [[long_2]]\n" +
7494 "%main = OpFunction %void None %void_func\n" +
7495 "%main_lab = OpLabel\n" +
7496 "%var = OpVariable %_ptr_long Function\n" +
7497 "%2 = OpLoad %long %var\n" +
7498 "%3 = OpSNegate %long %2\n" +
7499 "%4 = OpISub %long %long_2 %3\n" +
7500 "OpReturn\n" +
7501 "OpFunctionEnd\n",
7502 4, true),
7503 // Test case 4: merge add of subtract
7504 // (x + 2) - 1 = x + 1
7505 InstructionFoldingCase<bool>(
7506 Header() +
7507 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7508 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7509 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7510 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7511 "%main = OpFunction %void None %void_func\n" +
7512 "%main_lab = OpLabel\n" +
7513 "%var = OpVariable %_ptr_float Function\n" +
7514 "%2 = OpLoad %float %var\n" +
7515 "%3 = OpFAdd %float %2 %float_2\n" +
7516 "%4 = OpFSub %float %3 %float_1\n" +
7517 "OpReturn\n" +
7518 "OpFunctionEnd\n",
7519 4, true),
7520 // Test case 5: merge add of subtract
7521 // (2 + x) - 1 = x + 1
7522 InstructionFoldingCase<bool>(
7523 Header() +
7524 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7525 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7526 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7527 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7528 "%main = OpFunction %void None %void_func\n" +
7529 "%main_lab = OpLabel\n" +
7530 "%var = OpVariable %_ptr_float Function\n" +
7531 "%2 = OpLoad %float %var\n" +
7532 "%3 = OpFAdd %float %float_2 %2\n" +
7533 "%4 = OpFSub %float %3 %float_1\n" +
7534 "OpReturn\n" +
7535 "OpFunctionEnd\n",
7536 4, true),
7537 // Test case 6: merge add of subtract
7538 // 2 - (x + 1) = 1 - x
7539 InstructionFoldingCase<bool>(
7540 Header() +
7541 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7542 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7543 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7544 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
7545 "%main = OpFunction %void None %void_func\n" +
7546 "%main_lab = OpLabel\n" +
7547 "%var = OpVariable %_ptr_float Function\n" +
7548 "%2 = OpLoad %float %var\n" +
7549 "%3 = OpFAdd %float %2 %float_1\n" +
7550 "%4 = OpFSub %float %float_2 %3\n" +
7551 "OpReturn\n" +
7552 "OpFunctionEnd\n",
7553 4, true),
7554 // Test case 7: merge add of subtract
7555 // 2 - (1 + x) = 1 - x
7556 InstructionFoldingCase<bool>(
7557 Header() +
7558 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7559 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7560 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7561 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
7562 "%main = OpFunction %void None %void_func\n" +
7563 "%main_lab = OpLabel\n" +
7564 "%var = OpVariable %_ptr_float Function\n" +
7565 "%2 = OpLoad %float %var\n" +
7566 "%3 = OpFAdd %float %float_1 %2\n" +
7567 "%4 = OpFSub %float %float_2 %3\n" +
7568 "OpReturn\n" +
7569 "OpFunctionEnd\n",
7570 4, true),
7571 // Test case 8: merge subtract of subtract
7572 // (x - 2) - 1 = x - 3
7573 InstructionFoldingCase<bool>(
7574 Header() +
7575 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7576 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7577 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7578 "; CHECK: %4 = OpFSub [[float]] [[ld]] [[float_3]]\n" +
7579 "%main = OpFunction %void None %void_func\n" +
7580 "%main_lab = OpLabel\n" +
7581 "%var = OpVariable %_ptr_float Function\n" +
7582 "%2 = OpLoad %float %var\n" +
7583 "%3 = OpFSub %float %2 %float_2\n" +
7584 "%4 = OpFSub %float %3 %float_1\n" +
7585 "OpReturn\n" +
7586 "OpFunctionEnd\n",
7587 4, true),
7588 // Test case 9: merge subtract of subtract
7589 // (2 - x) - 1 = 1 - x
7590 InstructionFoldingCase<bool>(
7591 Header() +
7592 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7593 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7594 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7595 "; CHECK: %4 = OpFSub [[float]] [[float_1]] [[ld]]\n" +
7596 "%main = OpFunction %void None %void_func\n" +
7597 "%main_lab = OpLabel\n" +
7598 "%var = OpVariable %_ptr_float Function\n" +
7599 "%2 = OpLoad %float %var\n" +
7600 "%3 = OpFSub %float %float_2 %2\n" +
7601 "%4 = OpFSub %float %3 %float_1\n" +
7602 "OpReturn\n" +
7603 "OpFunctionEnd\n",
7604 4, true),
7605 // Test case 10: merge subtract of subtract
7606 // 2 - (x - 1) = 3 - x
7607 InstructionFoldingCase<bool>(
7608 Header() +
7609 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7610 "; CHECK: [[float_3:%\\w+]] = OpConstant [[float]] 3\n" +
7611 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7612 "; CHECK: %4 = OpFSub [[float]] [[float_3]] [[ld]]\n" +
7613 "%main = OpFunction %void None %void_func\n" +
7614 "%main_lab = OpLabel\n" +
7615 "%var = OpVariable %_ptr_float Function\n" +
7616 "%2 = OpLoad %float %var\n" +
7617 "%3 = OpFSub %float %2 %float_1\n" +
7618 "%4 = OpFSub %float %float_2 %3\n" +
7619 "OpReturn\n" +
7620 "OpFunctionEnd\n",
7621 4, true),
7622 // Test case 11: merge subtract of subtract
7623 // 1 - (2 - x) = x + (-1)
7624 InstructionFoldingCase<bool>(
7625 Header() +
7626 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7627 "; CHECK: [[float_n1:%\\w+]] = OpConstant [[float]] -1\n" +
7628 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7629 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_n1]]\n" +
7630 "%main = OpFunction %void None %void_func\n" +
7631 "%main_lab = OpLabel\n" +
7632 "%var = OpVariable %_ptr_float Function\n" +
7633 "%2 = OpLoad %float %var\n" +
7634 "%3 = OpFSub %float %float_2 %2\n" +
7635 "%4 = OpFSub %float %float_1 %3\n" +
7636 "OpReturn\n" +
7637 "OpFunctionEnd\n",
7638 4, true),
7639 // Test case 12: merge subtract of subtract
7640 // 2 - (1 - x) = x + 1
7641 InstructionFoldingCase<bool>(
7642 Header() +
7643 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
7644 "; CHECK: [[float_1:%\\w+]] = OpConstant [[float]] 1\n" +
7645 "; CHECK: [[ld:%\\w+]] = OpLoad [[float]]\n" +
7646 "; CHECK: %4 = OpFAdd [[float]] [[ld]] [[float_1]]\n" +
7647 "%main = OpFunction %void None %void_func\n" +
7648 "%main_lab = OpLabel\n" +
7649 "%var = OpVariable %_ptr_float Function\n" +
7650 "%2 = OpLoad %float %var\n" +
7651 "%3 = OpFSub %float %float_1 %2\n" +
7652 "%4 = OpFSub %float %float_2 %3\n" +
7653 "OpReturn\n" +
7654 "OpFunctionEnd\n",
7655 4, true),
7656 // Test case 13: merge subtract of subtract with mixed types.
7657 // 2 - (1 - x) = x + 1
7658 InstructionFoldingCase<bool>(
7659 Header() +
7660 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7661 "; CHECK: [[int_1:%\\w+]] = OpConstant [[int]] 1\n" +
7662 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
7663 "; CHECK: %4 = OpIAdd [[int]] [[ld]] [[int_1]]\n" +
7664 "%main = OpFunction %void None %void_func\n" +
7665 "%main_lab = OpLabel\n" +
7666 "%var = OpVariable %_ptr_int Function\n" +
7667 "%2 = OpLoad %int %var\n" +
7668 "%3 = OpISub %int %uint_1 %2\n" +
7669 "%4 = OpISub %int %int_2 %3\n" +
7670 "OpReturn\n" +
7671 "OpFunctionEnd\n",
7672 4, true),
7673 // Test case 14: fold overflowing signed 32 bit isubs
7674 // (x - int_max) - 1 = x - int_min
7675 InstructionFoldingCase<bool>(
7676 Header() +
7677 "; CHECK: [[int:%\\w+]] = OpTypeInt 32\n" +
7678 "; CHECK: [[int_min:%\\w+]] = OpConstant [[int]] -2147483648\n" +
7679 "; CHECK: [[ld:%\\w+]] = OpLoad [[int]]\n" +
7680 "; CHECK: %4 = OpISub [[int]] [[ld]] [[int_min]]\n" +
7681 "%main = OpFunction %void None %void_func\n" +
7682 "%main_lab = OpLabel\n" +
7683 "%var = OpVariable %_ptr_int Function\n" +
7684 "%2 = OpLoad %int %var\n" +
7685 "%3 = OpISub %int %2 %int_max\n" +
7686 "%4 = OpISub %int %3 %int_1\n" +
7687 "OpReturn\n" +
7688 "OpFunctionEnd\n",
7689 4, true),
7690 // Test case 15: fold overflowing signed 64 bit isubs
7691 // (x - long_max) - 1 = x - long_min
7692 InstructionFoldingCase<bool>(
7693 Header() +
7694 "; CHECK: [[long:%\\w+]] = OpTypeInt 64\n" +
7695 "; CHECK: [[long_min:%\\w+]] = OpConstant [[long]] -9223372036854775808\n" +
7696 "; CHECK: [[ld:%\\w+]] = OpLoad [[long]]\n" +
7697 "; CHECK: %4 = OpISub [[long]] [[ld]] [[long_min]]\n" +
7698 "%main = OpFunction %void None %void_func\n" +
7699 "%main_lab = OpLabel\n" +
7700 "%var = OpVariable %_ptr_long Function\n" +
7701 "%2 = OpLoad %long %var\n" +
7702 "%3 = OpISub %long %2 %long_max\n" +
7703 "%4 = OpISub %long %3 %long_1\n" +
7704 "OpReturn\n" +
7705 "OpFunctionEnd\n",
7706 4, true)
7707 ));
7708
7709 INSTANTIATE_TEST_SUITE_P(SelectFoldingTest, MatchingInstructionFoldingTest,
7710 ::testing::Values(
7711 // Test case 0: Fold select with the same values for both sides
7712 InstructionFoldingCase<bool>(
7713 Header() +
7714 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7715 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7716 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7717 "%main = OpFunction %void None %void_func\n" +
7718 "%main_lab = OpLabel\n" +
7719 "%n = OpVariable %_ptr_bool Function\n" +
7720 "%load = OpLoad %bool %n\n" +
7721 "%2 = OpSelect %int %load %100 %100\n" +
7722 "OpReturn\n" +
7723 "OpFunctionEnd",
7724 2, true),
7725 // Test case 1: Fold select true to left side
7726 InstructionFoldingCase<bool>(
7727 Header() +
7728 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7729 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7730 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7731 "%main = OpFunction %void None %void_func\n" +
7732 "%main_lab = OpLabel\n" +
7733 "%n = OpVariable %_ptr_int Function\n" +
7734 "%load = OpLoad %bool %n\n" +
7735 "%2 = OpSelect %int %true %100 %n\n" +
7736 "OpReturn\n" +
7737 "OpFunctionEnd",
7738 2, true),
7739 // Test case 2: Fold select false to right side
7740 InstructionFoldingCase<bool>(
7741 Header() +
7742 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7743 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7744 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7745 "%main = OpFunction %void None %void_func\n" +
7746 "%main_lab = OpLabel\n" +
7747 "%n = OpVariable %_ptr_int Function\n" +
7748 "%load = OpLoad %bool %n\n" +
7749 "%2 = OpSelect %int %false %n %100\n" +
7750 "OpReturn\n" +
7751 "OpFunctionEnd",
7752 2, true),
7753 // Test case 3: Fold select null to right side
7754 InstructionFoldingCase<bool>(
7755 Header() +
7756 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7757 "; CHECK: [[int0:%\\w+]] = OpConstant [[int]] 0\n" +
7758 "; CHECK: %2 = OpCopyObject [[int]] [[int0]]\n" +
7759 "%main = OpFunction %void None %void_func\n" +
7760 "%main_lab = OpLabel\n" +
7761 "%n = OpVariable %_ptr_int Function\n" +
7762 "%load = OpLoad %int %n\n" +
7763 "%2 = OpSelect %int %bool_null %load %100\n" +
7764 "OpReturn\n" +
7765 "OpFunctionEnd",
7766 2, true),
7767 // Test case 4: vector null
7768 InstructionFoldingCase<bool>(
7769 Header() +
7770 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7771 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
7772 "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7773 "; CHECK: [[v2int2_2:%\\w+]] = OpConstantComposite [[v2int]] [[int2]] [[int2]]\n" +
7774 "; CHECK: %2 = OpCopyObject [[v2int]] [[v2int2_2]]\n" +
7775 "%main = OpFunction %void None %void_func\n" +
7776 "%main_lab = OpLabel\n" +
7777 "%n = OpVariable %_ptr_v2int Function\n" +
7778 "%load = OpLoad %v2int %n\n" +
7779 "%2 = OpSelect %v2int %v2bool_null %load %v2int_2_2\n" +
7780 "OpReturn\n" +
7781 "OpFunctionEnd",
7782 2, true),
7783 // Test case 5: vector select
7784 InstructionFoldingCase<bool>(
7785 Header() +
7786 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7787 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
7788 "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 0 3\n" +
7789 "%main = OpFunction %void None %void_func\n" +
7790 "%main_lab = OpLabel\n" +
7791 "%m = OpVariable %_ptr_v2int Function\n" +
7792 "%n = OpVariable %_ptr_v2int Function\n" +
7793 "%2 = OpLoad %v2int %n\n" +
7794 "%3 = OpLoad %v2int %n\n" +
7795 "%4 = OpSelect %v2int %v2bool_true_false %2 %3\n" +
7796 "OpReturn\n" +
7797 "OpFunctionEnd",
7798 4, true),
7799 // Test case 6: vector select
7800 InstructionFoldingCase<bool>(
7801 Header() +
7802 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7803 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2\n" +
7804 "; CHECK: %4 = OpVectorShuffle [[v2int]] %2 %3 2 1\n" +
7805 "%main = OpFunction %void None %void_func\n" +
7806 "%main_lab = OpLabel\n" +
7807 "%m = OpVariable %_ptr_v2int Function\n" +
7808 "%n = OpVariable %_ptr_v2int Function\n" +
7809 "%2 = OpLoad %v2int %n\n" +
7810 "%3 = OpLoad %v2int %n\n" +
7811 "%4 = OpSelect %v2int %v2bool_false_true %2 %3\n" +
7812 "OpReturn\n" +
7813 "OpFunctionEnd",
7814 4, true)
7815 ));
7816
7817 INSTANTIATE_TEST_SUITE_P(CompositeExtractOrInsertMatchingTest, MatchingInstructionFoldingTest,
7818 ::testing::Values(
7819 // Test case 0: Extracting from result of consecutive shuffles of differing
7820 // size.
7821 InstructionFoldingCase<bool>(
7822 Header() +
7823 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7824 "; CHECK: %5 = OpCompositeExtract [[int]] %2 2\n" +
7825 "%main = OpFunction %void None %void_func\n" +
7826 "%main_lab = OpLabel\n" +
7827 "%n = OpVariable %_ptr_v4int Function\n" +
7828 "%2 = OpLoad %v4int %n\n" +
7829 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
7830 "%4 = OpVectorShuffle %v4int %2 %3 0 4 2 5\n" +
7831 "%5 = OpCompositeExtract %int %4 1\n" +
7832 "OpReturn\n" +
7833 "OpFunctionEnd",
7834 5, true),
7835 // Test case 1: Extracting from result of vector shuffle of differing
7836 // input and result sizes.
7837 InstructionFoldingCase<bool>(
7838 Header() +
7839 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7840 "; CHECK: %4 = OpCompositeExtract [[int]] %2 2\n" +
7841 "%main = OpFunction %void None %void_func\n" +
7842 "%main_lab = OpLabel\n" +
7843 "%n = OpVariable %_ptr_v4int Function\n" +
7844 "%2 = OpLoad %v4int %n\n" +
7845 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
7846 "%4 = OpCompositeExtract %int %3 0\n" +
7847 "OpReturn\n" +
7848 "OpFunctionEnd",
7849 4, true),
7850 // Test case 2: Extracting from result of vector shuffle of differing
7851 // input and result sizes.
7852 InstructionFoldingCase<bool>(
7853 Header() +
7854 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7855 "; CHECK: %4 = OpCompositeExtract [[int]] %2 3\n" +
7856 "%main = OpFunction %void None %void_func\n" +
7857 "%main_lab = OpLabel\n" +
7858 "%n = OpVariable %_ptr_v4int Function\n" +
7859 "%2 = OpLoad %v4int %n\n" +
7860 "%3 = OpVectorShuffle %v2int %2 %2 2 3\n" +
7861 "%4 = OpCompositeExtract %int %3 1\n" +
7862 "OpReturn\n" +
7863 "OpFunctionEnd",
7864 4, true),
7865 // Test case 3: Using fmix feeding extract with a 1 in the a position.
7866 InstructionFoldingCase<bool>(
7867 Header() +
7868 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7869 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
7870 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
7871 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7872 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7873 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[n]]\n" +
7874 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 1\n" +
7875 "%main = OpFunction %void None %void_func\n" +
7876 "%main_lab = OpLabel\n" +
7877 "%m = OpVariable %_ptr_v4double Function\n" +
7878 "%n = OpVariable %_ptr_v4double Function\n" +
7879 "%2 = OpLoad %v4double %m\n" +
7880 "%3 = OpLoad %v4double %n\n" +
7881 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
7882 "%5 = OpCompositeExtract %double %4 1\n" +
7883 "OpReturn\n" +
7884 "OpFunctionEnd",
7885 5, true),
7886 // Test case 4: Using fmix feeding extract with a 0 in the a position.
7887 InstructionFoldingCase<bool>(
7888 Header() +
7889 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7890 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
7891 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
7892 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7893 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7894 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
7895 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 2\n" +
7896 "%main = OpFunction %void None %void_func\n" +
7897 "%main_lab = OpLabel\n" +
7898 "%m = OpVariable %_ptr_v4double Function\n" +
7899 "%n = OpVariable %_ptr_v4double Function\n" +
7900 "%2 = OpLoad %v4double %m\n" +
7901 "%3 = OpLoad %v4double %n\n" +
7902 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_0_1_0_0\n" +
7903 "%5 = OpCompositeExtract %double %4 2\n" +
7904 "OpReturn\n" +
7905 "OpFunctionEnd",
7906 5, true),
7907 // Test case 5: Using fmix feeding extract with a null for the alpha
7908 InstructionFoldingCase<bool>(
7909 Header() +
7910 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
7911 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 4\n" +
7912 "; CHECK: [[ptr_v4double:%\\w+]] = OpTypePointer Function [[v4double]]\n" +
7913 "; CHECK: [[m:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7914 "; CHECK: [[n:%\\w+]] = OpVariable [[ptr_v4double]] Function\n" +
7915 "; CHECK: [[ld:%\\w+]] = OpLoad [[v4double]] [[m]]\n" +
7916 "; CHECK: %5 = OpCompositeExtract [[double]] [[ld]] 0\n" +
7917 "%main = OpFunction %void None %void_func\n" +
7918 "%main_lab = OpLabel\n" +
7919 "%m = OpVariable %_ptr_v4double Function\n" +
7920 "%n = OpVariable %_ptr_v4double Function\n" +
7921 "%2 = OpLoad %v4double %m\n" +
7922 "%3 = OpLoad %v4double %n\n" +
7923 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_null\n" +
7924 "%5 = OpCompositeExtract %double %4 0\n" +
7925 "OpReturn\n" +
7926 "OpFunctionEnd",
7927 5, true),
7928 // Test case 6: Don't fold: Using fmix feeding extract with 0.5 in the a
7929 // position.
7930 InstructionFoldingCase<bool>(
7931 Header() +
7932 "%main = OpFunction %void None %void_func\n" +
7933 "%main_lab = OpLabel\n" +
7934 "%m = OpVariable %_ptr_v4double Function\n" +
7935 "%n = OpVariable %_ptr_v4double Function\n" +
7936 "%2 = OpLoad %v4double %m\n" +
7937 "%3 = OpLoad %v4double %n\n" +
7938 "%4 = OpExtInst %v4double %1 FMix %2 %3 %v4double_1_1_1_0p5\n" +
7939 "%5 = OpCompositeExtract %double %4 3\n" +
7940 "OpReturn\n" +
7941 "OpFunctionEnd",
7942 5, false),
7943 // Test case 7: Extracting the undefined literal value from a vector
7944 // shuffle.
7945 InstructionFoldingCase<bool>(
7946 Header() +
7947 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7948 "; CHECK: %4 = OpUndef [[int]]\n" +
7949 "%main = OpFunction %void None %void_func\n" +
7950 "%main_lab = OpLabel\n" +
7951 "%n = OpVariable %_ptr_v4int Function\n" +
7952 "%2 = OpLoad %v4int %n\n" +
7953 "%3 = OpVectorShuffle %v2int %2 %2 2 4294967295\n" +
7954 "%4 = OpCompositeExtract %int %3 1\n" +
7955 "OpReturn\n" +
7956 "OpFunctionEnd",
7957 4, true),
7958 // Test case 8: Inserting every element of a vector turns into a composite construct.
7959 InstructionFoldingCase<bool>(
7960 Header() +
7961 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7962 "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
7963 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7964 "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7965 "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
7966 "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
7967 "; CHECK: %5 = OpCopyObject [[v4]] [[construct]]\n" +
7968 "%main = OpFunction %void None %void_func\n" +
7969 "%main_lab = OpLabel\n" +
7970 "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
7971 "%3 = OpCompositeInsert %v4int %int_1 %2 1\n" +
7972 "%4 = OpCompositeInsert %v4int %int_2 %3 2\n" +
7973 "%5 = OpCompositeInsert %v4int %int_3 %4 3\n" +
7974 "OpReturn\n" +
7975 "OpFunctionEnd",
7976 5, true),
7977 // Test case 9: Inserting every element of a vector turns into a composite construct in a different order.
7978 InstructionFoldingCase<bool>(
7979 Header() +
7980 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
7981 "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
7982 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
7983 "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
7984 "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
7985 "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
7986 "; CHECK: %5 = OpCopyObject [[v4]] [[construct]]\n" +
7987 "%main = OpFunction %void None %void_func\n" +
7988 "%main_lab = OpLabel\n" +
7989 "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
7990 "%4 = OpCompositeInsert %v4int %int_2 %2 2\n" +
7991 "%3 = OpCompositeInsert %v4int %int_1 %4 1\n" +
7992 "%5 = OpCompositeInsert %v4int %int_3 %3 3\n" +
7993 "OpReturn\n" +
7994 "OpFunctionEnd",
7995 5, true),
7996 // Test case 10: Check multiple inserts to the same position are handled correctly.
7997 InstructionFoldingCase<bool>(
7998 Header() +
7999 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
8000 "; CHECK-DAG: [[v4:%\\w+]] = OpTypeVector [[int]] 4\n" +
8001 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
8002 "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
8003 "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
8004 "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v4]] %100 [[int1]] [[int2]] [[int3]]\n" +
8005 "; CHECK: %6 = OpCopyObject [[v4]] [[construct]]\n" +
8006 "%main = OpFunction %void None %void_func\n" +
8007 "%main_lab = OpLabel\n" +
8008 "%2 = OpCompositeInsert %v4int %100 %v4int_undef 0\n" +
8009 "%3 = OpCompositeInsert %v4int %int_2 %2 2\n" +
8010 "%4 = OpCompositeInsert %v4int %int_4 %3 1\n" +
8011 "%5 = OpCompositeInsert %v4int %int_1 %4 1\n" +
8012 "%6 = OpCompositeInsert %v4int %int_3 %5 3\n" +
8013 "OpReturn\n" +
8014 "OpFunctionEnd",
8015 6, true),
8016 // Test case 11: The last indexes are 0 and 1, but they have different first indexes. This should not be folded.
8017 InstructionFoldingCase<bool>(
8018 Header() +
8019 "%main = OpFunction %void None %void_func\n" +
8020 "%main_lab = OpLabel\n" +
8021 "%2 = OpCompositeInsert %m2x2int %100 %m2x2int_undef 0 0\n" +
8022 "%3 = OpCompositeInsert %m2x2int %int_1 %2 1 1\n" +
8023 "OpReturn\n" +
8024 "OpFunctionEnd",
8025 3, false),
8026 // Test case 12: Don't fold when there is a partial insertion.
8027 InstructionFoldingCase<bool>(
8028 Header() +
8029 "%main = OpFunction %void None %void_func\n" +
8030 "%main_lab = OpLabel\n" +
8031 "%2 = OpCompositeInsert %m2x2int %v2int_1_0 %m2x2int_undef 0\n" +
8032 "%3 = OpCompositeInsert %m2x2int %int_4 %2 0 0\n" +
8033 "%4 = OpCompositeInsert %m2x2int %v2int_2_3 %3 1\n" +
8034 "OpReturn\n" +
8035 "OpFunctionEnd",
8036 4, false),
8037 // Test case 13: Insert into a column of a matrix
8038 InstructionFoldingCase<bool>(
8039 Header() +
8040 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
8041 "; CHECK-DAG: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
8042 "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
8043 "; CHECK-DAG: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
8044 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
8045 // We keep this insert in the chain. DeadInsertElimPass should remove it.
8046 "; CHECK: [[insert:%\\w+]] = OpCompositeInsert [[m2x2]] %100 [[m2x2_undef]] 0 0\n" +
8047 "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[v2]] %100 [[int1]]\n" +
8048 "; CHECK: %3 = OpCompositeInsert [[m2x2]] [[construct]] [[insert]] 0\n" +
8049 "%main = OpFunction %void None %void_func\n" +
8050 "%main_lab = OpLabel\n" +
8051 "%2 = OpCompositeInsert %m2x2int %100 %m2x2int_undef 0 0\n" +
8052 "%3 = OpCompositeInsert %m2x2int %int_1 %2 0 1\n" +
8053 "OpReturn\n" +
8054 "OpFunctionEnd",
8055 3, true),
8056 // Test case 14: Insert all elements of the matrix.
8057 InstructionFoldingCase<bool>(
8058 Header() +
8059 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
8060 "; CHECK-DAG: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
8061 "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
8062 "; CHECK-DAG: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
8063 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
8064 "; CHECK-DAG: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
8065 "; CHECK-DAG: [[int3:%\\w+]] = OpConstant [[int]] 3\n" +
8066 "; CHECK: [[c0:%\\w+]] = OpCompositeConstruct [[v2]] %100 [[int1]]\n" +
8067 "; CHECK: [[c1:%\\w+]] = OpCompositeConstruct [[v2]] [[int2]] [[int3]]\n" +
8068 "; CHECK: [[matrix:%\\w+]] = OpCompositeConstruct [[m2x2]] [[c0]] [[c1]]\n" +
8069 "; CHECK: %5 = OpCopyObject [[m2x2]] [[matrix]]\n" +
8070 "%main = OpFunction %void None %void_func\n" +
8071 "%main_lab = OpLabel\n" +
8072 "%2 = OpCompositeConstruct %v2int %100 %int_1\n" +
8073 "%3 = OpCompositeInsert %m2x2int %2 %m2x2int_undef 0\n" +
8074 "%4 = OpCompositeInsert %m2x2int %int_2 %3 1 0\n" +
8075 "%5 = OpCompositeInsert %m2x2int %int_3 %4 1 1\n" +
8076 "OpReturn\n" +
8077 "OpFunctionEnd",
8078 5, true),
8079 // Test case 15: Replace construct with extract when reconstructing a member
8080 // of another object.
8081 InstructionFoldingCase<bool>(
8082 Header() +
8083 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
8084 "; CHECK: [[v2:%\\w+]] = OpTypeVector [[int]] 2\n" +
8085 "; CHECK: [[m2x2:%\\w+]] = OpTypeMatrix [[v2]] 2\n" +
8086 "; CHECK: [[m2x2_undef:%\\w+]] = OpUndef [[m2x2]]\n" +
8087 "; CHECK: %5 = OpCompositeExtract [[v2]] [[m2x2_undef]]\n" +
8088 "%main = OpFunction %void None %void_func\n" +
8089 "%main_lab = OpLabel\n" +
8090 "%3 = OpCompositeExtract %int %m2x2int_undef 1 0\n" +
8091 "%4 = OpCompositeExtract %int %m2x2int_undef 1 1\n" +
8092 "%5 = OpCompositeConstruct %v2int %3 %4\n" +
8093 "OpReturn\n" +
8094 "OpFunctionEnd",
8095 5, true),
8096 // Test case 16: Don't fold when type cannot be deduced to a constant.
8097 InstructionFoldingCase<bool>(
8098 Header() +
8099 "%main = OpFunction %void None %void_func\n" +
8100 "%main_lab = OpLabel\n" +
8101 "%4 = OpCompositeInsert %struct_v2int_int_int %int_1 %struct_v2int_int_int_null 2\n" +
8102 "OpReturn\n" +
8103 "OpFunctionEnd",
8104 4, false),
8105 // Test case 17: Don't fold when index into composite is out of bounds.
8106 InstructionFoldingCase<bool>(
8107 Header() +
8108 "%main = OpFunction %void None %void_func\n" +
8109 "%main_lab = OpLabel\n" +
8110 "%4 = OpCompositeExtract %int %struct_v2int_int_int 3\n" +
8111 "OpReturn\n" +
8112 "OpFunctionEnd",
8113 4, false),
8114 // Test case 18: Fold when every element of an array is inserted.
8115 InstructionFoldingCase<bool>(
8116 Header() +
8117 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
8118 "; CHECK: [[int2:%\\w+]] = OpConstant [[int]] 2\n" +
8119 "; CHECK-DAG: [[arr_type:%\\w+]] = OpTypeArray [[int]] [[int2]]\n" +
8120 "; CHECK-DAG: [[int10:%\\w+]] = OpConstant [[int]] 10\n" +
8121 "; CHECK-DAG: [[int1:%\\w+]] = OpConstant [[int]] 1\n" +
8122 "; CHECK: [[construct:%\\w+]] = OpCompositeConstruct [[arr_type]] [[int10]] [[int1]]\n" +
8123 "; CHECK: %5 = OpCopyObject [[arr_type]] [[construct]]\n" +
8124 "%main = OpFunction %void None %void_func\n" +
8125 "%main_lab = OpLabel\n" +
8126 "%4 = OpCompositeInsert %int_arr_2 %int_10 %int_arr_2_undef 0\n" +
8127 "%5 = OpCompositeInsert %int_arr_2 %int_1 %4 1\n" +
8128 "OpReturn\n" +
8129 "OpFunctionEnd",
8130 5, true),
8131 // Test case 19: Don't fold for isomorphic structs
8132 InstructionFoldingCase<bool>(
8133 Header() +
8134 "%structA = OpTypeStruct %ulong\n" +
8135 "%structB = OpTypeStruct %ulong\n" +
8136 "%structC = OpTypeStruct %structB\n" +
8137 "%struct_a_undef = OpUndef %structA\n" +
8138 "%main = OpFunction %void None %void_func\n" +
8139 "%main_lab = OpLabel\n" +
8140 "%3 = OpCompositeExtract %ulong %struct_a_undef 0\n" +
8141 "%4 = OpCompositeConstruct %structB %3\n" +
8142 "OpReturn\n" +
8143 "OpFunctionEnd",
8144 4, false)
8145 ));
8146
8147 INSTANTIATE_TEST_SUITE_P(DotProductMatchingTest, MatchingInstructionFoldingTest,
8148 ::testing::Values(
8149 // Test case 0: Using OpDot to extract last element.
8150 InstructionFoldingCase<bool>(
8151 Header() +
8152 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
8153 "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
8154 "%main = OpFunction %void None %void_func\n" +
8155 "%main_lab = OpLabel\n" +
8156 "%n = OpVariable %_ptr_v4float Function\n" +
8157 "%2 = OpLoad %v4float %n\n" +
8158 "%3 = OpDot %float %2 %v4float_0_0_0_1\n" +
8159 "OpReturn\n" +
8160 "OpFunctionEnd",
8161 3, true),
8162 // Test case 1: Using OpDot to extract last element.
8163 InstructionFoldingCase<bool>(
8164 Header() +
8165 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
8166 "; CHECK: %3 = OpCompositeExtract [[float]] %2 3\n" +
8167 "%main = OpFunction %void None %void_func\n" +
8168 "%main_lab = OpLabel\n" +
8169 "%n = OpVariable %_ptr_v4float Function\n" +
8170 "%2 = OpLoad %v4float %n\n" +
8171 "%3 = OpDot %float %v4float_0_0_0_1 %2\n" +
8172 "OpReturn\n" +
8173 "OpFunctionEnd",
8174 3, true),
8175 // Test case 2: Using OpDot to extract second element.
8176 InstructionFoldingCase<bool>(
8177 Header() +
8178 "; CHECK: [[float:%\\w+]] = OpTypeFloat 32\n" +
8179 "; CHECK: %3 = OpCompositeExtract [[float]] %2 1\n" +
8180 "%main = OpFunction %void None %void_func\n" +
8181 "%main_lab = OpLabel\n" +
8182 "%n = OpVariable %_ptr_v4float Function\n" +
8183 "%2 = OpLoad %v4float %n\n" +
8184 "%3 = OpDot %float %v4float_0_1_0_0 %2\n" +
8185 "OpReturn\n" +
8186 "OpFunctionEnd",
8187 3, true),
8188 // Test case 3: Using OpDot to extract last element.
8189 InstructionFoldingCase<bool>(
8190 Header() +
8191 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8192 "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
8193 "%main = OpFunction %void None %void_func\n" +
8194 "%main_lab = OpLabel\n" +
8195 "%n = OpVariable %_ptr_v4double Function\n" +
8196 "%2 = OpLoad %v4double %n\n" +
8197 "%3 = OpDot %double %2 %v4double_0_0_0_1\n" +
8198 "OpReturn\n" +
8199 "OpFunctionEnd",
8200 3, true),
8201 // Test case 4: Using OpDot to extract last element.
8202 InstructionFoldingCase<bool>(
8203 Header() +
8204 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8205 "; CHECK: %3 = OpCompositeExtract [[double]] %2 3\n" +
8206 "%main = OpFunction %void None %void_func\n" +
8207 "%main_lab = OpLabel\n" +
8208 "%n = OpVariable %_ptr_v4double Function\n" +
8209 "%2 = OpLoad %v4double %n\n" +
8210 "%3 = OpDot %double %v4double_0_0_0_1 %2\n" +
8211 "OpReturn\n" +
8212 "OpFunctionEnd",
8213 3, true),
8214 // Test case 5: Using OpDot to extract second element.
8215 InstructionFoldingCase<bool>(
8216 Header() +
8217 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8218 "; CHECK: %3 = OpCompositeExtract [[double]] %2 1\n" +
8219 "%main = OpFunction %void None %void_func\n" +
8220 "%main_lab = OpLabel\n" +
8221 "%n = OpVariable %_ptr_v4double Function\n" +
8222 "%2 = OpLoad %v4double %n\n" +
8223 "%3 = OpDot %double %v4double_0_1_0_0 %2\n" +
8224 "OpReturn\n" +
8225 "OpFunctionEnd",
8226 3, true)
8227 ));
8228
8229 INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionFoldingTest,
8230 ::testing::Values(
8231 // Test case 0: Using OpDot to extract last element.
8232 InstructionFoldingCase<bool>(
8233 Header() +
8234 "; CHECK: [[int:%\\w+]] = OpTypeInt 32 1\n" +
8235 "; CHECK: [[v2int:%\\w+]] = OpTypeVector [[int]] 2{{[[:space:]]}}\n" +
8236 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v2int]]\n" +
8237 "; CHECK: OpVectorShuffle\n" +
8238 "; CHECK: %3 = OpVectorShuffle [[v2int]] [[null]] {{%\\w+}} 4294967295 2\n" +
8239 "%main = OpFunction %void None %void_func\n" +
8240 "%main_lab = OpLabel\n" +
8241 "%n = OpVariable %_ptr_int Function\n" +
8242 "%load = OpLoad %int %n\n" +
8243 "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 3 0xFFFFFFFF \n" +
8244 "%3 = OpVectorShuffle %v2int %2 %v2int_2_3 1 2 \n" +
8245 "OpReturn\n" +
8246 "OpFunctionEnd",
8247 3, true)
8248 ));
8249
8250 // Issue #5658: The Adreno compiler does not handle 16-bit FMA instructions well.
8251 // We want to avoid this by not generating FMA. We decided to never generate
8252 // FMAs because, from a SPIR-V perspective, it is neutral. The ICD can generate
8253 // the FMA if it wants. The simplest code is no code.
8254 INSTANTIATE_TEST_SUITE_P(FmaGenerationMatchingTest, MatchingInstructionFoldingTest,
8255 ::testing::Values(
8256 // Test case 0: Don't fold (x * y) + a
8257 InstructionFoldingCase<bool>(
8258 Header() +
8259 "%main = OpFunction %void None %void_func\n" +
8260 "%main_lab = OpLabel\n" +
8261 "%x = OpVariable %_ptr_float Function\n" +
8262 "%y = OpVariable %_ptr_float Function\n" +
8263 "%a = OpVariable %_ptr_float Function\n" +
8264 "%lx = OpLoad %float %x\n" +
8265 "%ly = OpLoad %float %y\n" +
8266 "%mul = OpFMul %float %lx %ly\n" +
8267 "%la = OpLoad %float %a\n" +
8268 "%3 = OpFAdd %float %mul %la\n" +
8269 "OpStore %a %3\n" +
8270 "OpReturn\n" +
8271 "OpFunctionEnd",
8272 3, false),
8273 // Test case 1: Don't fold a + (x * y)
8274 InstructionFoldingCase<bool>(
8275 Header() +
8276 "%main = OpFunction %void None %void_func\n" +
8277 "%main_lab = OpLabel\n" +
8278 "%x = OpVariable %_ptr_float Function\n" +
8279 "%y = OpVariable %_ptr_float Function\n" +
8280 "%a = OpVariable %_ptr_float Function\n" +
8281 "%lx = OpLoad %float %x\n" +
8282 "%ly = OpLoad %float %y\n" +
8283 "%mul = OpFMul %float %lx %ly\n" +
8284 "%la = OpLoad %float %a\n" +
8285 "%3 = OpFAdd %float %la %mul\n" +
8286 "OpStore %a %3\n" +
8287 "OpReturn\n" +
8288 "OpFunctionEnd",
8289 3, false),
8290 // Test case 2: Don't fold (x * y) + a with vectors
8291 InstructionFoldingCase<bool>(
8292 Header() +
8293 "%main = OpFunction %void None %void_func\n" +
8294 "%main_lab = OpLabel\n" +
8295 "%x = OpVariable %_ptr_v4float Function\n" +
8296 "%y = OpVariable %_ptr_v4float Function\n" +
8297 "%a = OpVariable %_ptr_v4float Function\n" +
8298 "%lx = OpLoad %v4float %x\n" +
8299 "%ly = OpLoad %v4float %y\n" +
8300 "%mul = OpFMul %v4float %lx %ly\n" +
8301 "%la = OpLoad %v4float %a\n" +
8302 "%3 = OpFAdd %v4float %mul %la\n" +
8303 "OpStore %a %3\n" +
8304 "OpReturn\n" +
8305 "OpFunctionEnd",
8306 3,false),
8307 // Test case 3: Don't fold a + (x * y) with vectors
8308 InstructionFoldingCase<bool>(
8309 Header() +
8310 "%main = OpFunction %void None %void_func\n" +
8311 "%main_lab = OpLabel\n" +
8312 "%x = OpVariable %_ptr_float Function\n" +
8313 "%y = OpVariable %_ptr_float Function\n" +
8314 "%a = OpVariable %_ptr_float Function\n" +
8315 "%lx = OpLoad %float %x\n" +
8316 "%ly = OpLoad %float %y\n" +
8317 "%mul = OpFMul %float %lx %ly\n" +
8318 "%la = OpLoad %float %a\n" +
8319 "%3 = OpFAdd %float %la %mul\n" +
8320 "OpStore %a %3\n" +
8321 "OpReturn\n" +
8322 "OpFunctionEnd",
8323 3, false),
8324 // Test 4: Don't fold if the multiple is marked no contract.
8325 InstructionFoldingCase<bool>(
8326 std::string() +
8327 "OpCapability Shader\n" +
8328 "OpMemoryModel Logical GLSL450\n" +
8329 "OpEntryPoint Fragment %main \"main\"\n" +
8330 "OpExecutionMode %main OriginUpperLeft\n" +
8331 "OpSource GLSL 140\n" +
8332 "OpName %main \"main\"\n" +
8333 "OpDecorate %mul NoContraction\n" +
8334 "%void = OpTypeVoid\n" +
8335 "%void_func = OpTypeFunction %void\n" +
8336 "%bool = OpTypeBool\n" +
8337 "%float = OpTypeFloat 32\n" +
8338 "%_ptr_float = OpTypePointer Function %float\n" +
8339 "%main = OpFunction %void None %void_func\n" +
8340 "%main_lab = OpLabel\n" +
8341 "%x = OpVariable %_ptr_float Function\n" +
8342 "%y = OpVariable %_ptr_float Function\n" +
8343 "%a = OpVariable %_ptr_float Function\n" +
8344 "%lx = OpLoad %float %x\n" +
8345 "%ly = OpLoad %float %y\n" +
8346 "%mul = OpFMul %float %lx %ly\n" +
8347 "%la = OpLoad %float %a\n" +
8348 "%3 = OpFAdd %float %mul %la\n" +
8349 "OpStore %a %3\n" +
8350 "OpReturn\n" +
8351 "OpFunctionEnd",
8352 3, false),
8353 // Test 5: Don't fold if the add is marked no contract.
8354 InstructionFoldingCase<bool>(
8355 std::string() +
8356 "OpCapability Shader\n" +
8357 "OpMemoryModel Logical GLSL450\n" +
8358 "OpEntryPoint Fragment %main \"main\"\n" +
8359 "OpExecutionMode %main OriginUpperLeft\n" +
8360 "OpSource GLSL 140\n" +
8361 "OpName %main \"main\"\n" +
8362 "OpDecorate %3 NoContraction\n" +
8363 "%void = OpTypeVoid\n" +
8364 "%void_func = OpTypeFunction %void\n" +
8365 "%bool = OpTypeBool\n" +
8366 "%float = OpTypeFloat 32\n" +
8367 "%_ptr_float = OpTypePointer Function %float\n" +
8368 "%main = OpFunction %void None %void_func\n" +
8369 "%main_lab = OpLabel\n" +
8370 "%x = OpVariable %_ptr_float Function\n" +
8371 "%y = OpVariable %_ptr_float Function\n" +
8372 "%a = OpVariable %_ptr_float Function\n" +
8373 "%lx = OpLoad %float %x\n" +
8374 "%ly = OpLoad %float %y\n" +
8375 "%mul = OpFMul %float %lx %ly\n" +
8376 "%la = OpLoad %float %a\n" +
8377 "%3 = OpFAdd %float %mul %la\n" +
8378 "OpStore %a %3\n" +
8379 "OpReturn\n" +
8380 "OpFunctionEnd",
8381 3, false),
8382 // Test case 6: Don't fold (x * y) - a
8383 InstructionFoldingCase<bool>(
8384 Header() +
8385 "%main = OpFunction %void None %void_func\n" +
8386 "%main_lab = OpLabel\n" +
8387 "%x = OpVariable %_ptr_float Function\n" +
8388 "%y = OpVariable %_ptr_float Function\n" +
8389 "%a = OpVariable %_ptr_float Function\n" +
8390 "%lx = OpLoad %float %x\n" +
8391 "%ly = OpLoad %float %y\n" +
8392 "%mul = OpFMul %float %lx %ly\n" +
8393 "%la = OpLoad %float %a\n" +
8394 "%3 = OpFSub %float %mul %la\n" +
8395 "OpStore %a %3\n" +
8396 "OpReturn\n" +
8397 "OpFunctionEnd",
8398 3, false),
8399 // Test case 7: Don't fold a - (x * y)
8400 InstructionFoldingCase<bool>(
8401 Header() +
8402 "%main = OpFunction %void None %void_func\n" +
8403 "%main_lab = OpLabel\n" +
8404 "%x = OpVariable %_ptr_float Function\n" +
8405 "%y = OpVariable %_ptr_float Function\n" +
8406 "%a = OpVariable %_ptr_float Function\n" +
8407 "%lx = OpLoad %float %x\n" +
8408 "%ly = OpLoad %float %y\n" +
8409 "%mul = OpFMul %float %lx %ly\n" +
8410 "%la = OpLoad %float %a\n" +
8411 "%3 = OpFSub %float %la %mul\n" +
8412 "OpStore %a %3\n" +
8413 "OpReturn\n" +
8414 "OpFunctionEnd",
8415 3, false)
8416 ));
8417
8418 using MatchingInstructionWithNoResultFoldingTest =
8419 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8420
8421 // Test folding instructions that do not have a result. The instruction
8422 // that will be folded is the last instruction before the return. If there
8423 // are multiple returns, there is not guarantee which one is used.
TEST_P(MatchingInstructionWithNoResultFoldingTest,Case)8424 TEST_P(MatchingInstructionWithNoResultFoldingTest, Case) {
8425 const auto& tc = GetParam();
8426
8427 std::unique_ptr<IRContext> context;
8428 Instruction* inst;
8429 std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_1);
8430
8431 // Find the instruction to test.
8432 EXPECT_EQ(inst != nullptr, tc.expected_result);
8433 if (inst != nullptr) {
8434 Match(tc.test_body, context.get());
8435 }
8436 }
8437
8438 INSTANTIATE_TEST_SUITE_P(StoreMatchingTest, MatchingInstructionWithNoResultFoldingTest,
8439 ::testing::Values(
8440 // Test case 0: Remove store of undef.
8441 InstructionFoldingCase<bool>(
8442 Header() +
8443 "; CHECK: OpLabel\n" +
8444 "; CHECK-NOT: OpStore\n" +
8445 "; CHECK: OpReturn\n" +
8446 "%main = OpFunction %void None %void_func\n" +
8447 "%main_lab = OpLabel\n" +
8448 "%n = OpVariable %_ptr_v4double Function\n" +
8449 "%undef = OpUndef %v4double\n" +
8450 "OpStore %n %undef\n" +
8451 "OpReturn\n" +
8452 "OpFunctionEnd",
8453 0 /* OpStore */, true),
8454 // Test case 1: Keep volatile store.
8455 InstructionFoldingCase<bool>(
8456 Header() +
8457 "%main = OpFunction %void None %void_func\n" +
8458 "%main_lab = OpLabel\n" +
8459 "%n = OpVariable %_ptr_v4double Function\n" +
8460 "%undef = OpUndef %v4double\n" +
8461 "OpStore %n %undef Volatile\n" +
8462 "OpReturn\n" +
8463 "OpFunctionEnd",
8464 0 /* OpStore */, false)
8465 ));
8466
8467 INSTANTIATE_TEST_SUITE_P(VectorShuffleMatchingTest, MatchingInstructionWithNoResultFoldingTest,
8468 ::testing::Values(
8469 // Test case 0: Basic test 1
8470 InstructionFoldingCase<bool>(
8471 Header() +
8472 "; CHECK: OpVectorShuffle\n" +
8473 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 3 6 7\n" +
8474 "; CHECK: OpReturn\n" +
8475 "%main = OpFunction %void None %void_func\n" +
8476 "%main_lab = OpLabel\n" +
8477 "%2 = OpVariable %_ptr_v4double Function\n" +
8478 "%3 = OpVariable %_ptr_v4double Function\n" +
8479 "%4 = OpVariable %_ptr_v4double Function\n" +
8480 "%5 = OpLoad %v4double %2\n" +
8481 "%6 = OpLoad %v4double %3\n" +
8482 "%7 = OpLoad %v4double %4\n" +
8483 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8484 "%9 = OpVectorShuffle %v4double %7 %8 2 3 4 5\n" +
8485 "OpReturn\n" +
8486 "OpFunctionEnd",
8487 9, true),
8488 // Test case 1: Basic test 2
8489 InstructionFoldingCase<bool>(
8490 Header() +
8491 "; CHECK: OpVectorShuffle\n" +
8492 "; CHECK: OpVectorShuffle {{%\\w+}} %6 %7 0 1 4 5\n" +
8493 "; CHECK: OpReturn\n" +
8494 "%main = OpFunction %void None %void_func\n" +
8495 "%main_lab = OpLabel\n" +
8496 "%2 = OpVariable %_ptr_v4double Function\n" +
8497 "%3 = OpVariable %_ptr_v4double Function\n" +
8498 "%4 = OpVariable %_ptr_v4double Function\n" +
8499 "%5 = OpLoad %v4double %2\n" +
8500 "%6 = OpLoad %v4double %3\n" +
8501 "%7 = OpLoad %v4double %4\n" +
8502 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8503 "%9 = OpVectorShuffle %v4double %8 %7 2 3 4 5\n" +
8504 "OpReturn\n" +
8505 "OpFunctionEnd",
8506 9, true),
8507 // Test case 2: Basic test 3
8508 InstructionFoldingCase<bool>(
8509 Header() +
8510 "; CHECK: OpVectorShuffle\n" +
8511 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 2 4 5\n" +
8512 "; CHECK: OpReturn\n" +
8513 "%main = OpFunction %void None %void_func\n" +
8514 "%main_lab = OpLabel\n" +
8515 "%2 = OpVariable %_ptr_v4double Function\n" +
8516 "%3 = OpVariable %_ptr_v4double Function\n" +
8517 "%4 = OpVariable %_ptr_v4double Function\n" +
8518 "%5 = OpLoad %v4double %2\n" +
8519 "%6 = OpLoad %v4double %3\n" +
8520 "%7 = OpLoad %v4double %4\n" +
8521 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8522 "%9 = OpVectorShuffle %v4double %8 %7 1 0 4 5\n" +
8523 "OpReturn\n" +
8524 "OpFunctionEnd",
8525 9, true),
8526 // Test case 3: Basic test 4
8527 InstructionFoldingCase<bool>(
8528 Header() +
8529 "; CHECK: OpVectorShuffle\n" +
8530 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %6 2 3 5 4\n" +
8531 "; CHECK: OpReturn\n" +
8532 "%main = OpFunction %void None %void_func\n" +
8533 "%main_lab = OpLabel\n" +
8534 "%2 = OpVariable %_ptr_v4double Function\n" +
8535 "%3 = OpVariable %_ptr_v4double Function\n" +
8536 "%4 = OpVariable %_ptr_v4double Function\n" +
8537 "%5 = OpLoad %v4double %2\n" +
8538 "%6 = OpLoad %v4double %3\n" +
8539 "%7 = OpLoad %v4double %4\n" +
8540 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8541 "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 6\n" +
8542 "OpReturn\n" +
8543 "OpFunctionEnd",
8544 9, true),
8545 // Test case 4: Don't fold, need both operands of the feeder.
8546 InstructionFoldingCase<bool>(
8547 Header() +
8548 "%main = OpFunction %void None %void_func\n" +
8549 "%main_lab = OpLabel\n" +
8550 "%2 = OpVariable %_ptr_v4double Function\n" +
8551 "%3 = OpVariable %_ptr_v4double Function\n" +
8552 "%4 = OpVariable %_ptr_v4double Function\n" +
8553 "%5 = OpLoad %v4double %2\n" +
8554 "%6 = OpLoad %v4double %3\n" +
8555 "%7 = OpLoad %v4double %4\n" +
8556 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8557 "%9 = OpVectorShuffle %v4double %7 %8 2 3 7 5\n" +
8558 "OpReturn\n" +
8559 "OpFunctionEnd",
8560 9, false),
8561 // Test case 5: Don't fold, need both operands of the feeder.
8562 InstructionFoldingCase<bool>(
8563 Header() +
8564 "%main = OpFunction %void None %void_func\n" +
8565 "%main_lab = OpLabel\n" +
8566 "%2 = OpVariable %_ptr_v4double Function\n" +
8567 "%3 = OpVariable %_ptr_v4double Function\n" +
8568 "%4 = OpVariable %_ptr_v4double Function\n" +
8569 "%5 = OpLoad %v4double %2\n" +
8570 "%6 = OpLoad %v4double %3\n" +
8571 "%7 = OpLoad %v4double %4\n" +
8572 "%8 = OpVectorShuffle %v4double %5 %6 2 3 4 5\n" +
8573 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
8574 "OpReturn\n" +
8575 "OpFunctionEnd",
8576 9, false),
8577 // Test case 6: Fold, need both operands of the feeder, but they are the same.
8578 InstructionFoldingCase<bool>(
8579 Header() +
8580 "; CHECK: OpVectorShuffle\n" +
8581 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 2 7 5\n" +
8582 "; CHECK: OpReturn\n" +
8583 "%main = OpFunction %void None %void_func\n" +
8584 "%main_lab = OpLabel\n" +
8585 "%2 = OpVariable %_ptr_v4double Function\n" +
8586 "%3 = OpVariable %_ptr_v4double Function\n" +
8587 "%4 = OpVariable %_ptr_v4double Function\n" +
8588 "%5 = OpLoad %v4double %2\n" +
8589 "%6 = OpLoad %v4double %3\n" +
8590 "%7 = OpLoad %v4double %4\n" +
8591 "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
8592 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
8593 "OpReturn\n" +
8594 "OpFunctionEnd",
8595 9, true),
8596 // Test case 7: Fold, need both operands of the feeder, but they are the same.
8597 InstructionFoldingCase<bool>(
8598 Header() +
8599 "; CHECK: OpVectorShuffle\n" +
8600 "; CHECK: OpVectorShuffle {{%\\w+}} %7 %5 2 0 5 7\n" +
8601 "; CHECK: OpReturn\n" +
8602 "%main = OpFunction %void None %void_func\n" +
8603 "%main_lab = OpLabel\n" +
8604 "%2 = OpVariable %_ptr_v4double Function\n" +
8605 "%3 = OpVariable %_ptr_v4double Function\n" +
8606 "%4 = OpVariable %_ptr_v4double Function\n" +
8607 "%5 = OpLoad %v4double %2\n" +
8608 "%6 = OpLoad %v4double %3\n" +
8609 "%7 = OpLoad %v4double %4\n" +
8610 "%8 = OpVectorShuffle %v4double %5 %5 2 3 4 5\n" +
8611 "%9 = OpVectorShuffle %v4double %7 %8 2 0 7 5\n" +
8612 "OpReturn\n" +
8613 "OpFunctionEnd",
8614 9, true),
8615 // Test case 8: Replace first operand with a smaller vector.
8616 InstructionFoldingCase<bool>(
8617 Header() +
8618 "; CHECK: OpVectorShuffle\n" +
8619 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 0 5 3\n" +
8620 "; CHECK: OpReturn\n" +
8621 "%main = OpFunction %void None %void_func\n" +
8622 "%main_lab = OpLabel\n" +
8623 "%2 = OpVariable %_ptr_v2double Function\n" +
8624 "%3 = OpVariable %_ptr_v4double Function\n" +
8625 "%4 = OpVariable %_ptr_v4double Function\n" +
8626 "%5 = OpLoad %v2double %2\n" +
8627 "%6 = OpLoad %v4double %3\n" +
8628 "%7 = OpLoad %v4double %4\n" +
8629 "%8 = OpVectorShuffle %v4double %5 %5 0 1 2 3\n" +
8630 "%9 = OpVectorShuffle %v4double %8 %7 2 0 7 5\n" +
8631 "OpReturn\n" +
8632 "OpFunctionEnd",
8633 9, true),
8634 // Test case 9: Replace first operand with a larger vector.
8635 InstructionFoldingCase<bool>(
8636 Header() +
8637 "; CHECK: OpVectorShuffle\n" +
8638 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 3 0 7 5\n" +
8639 "; CHECK: OpReturn\n" +
8640 "%main = OpFunction %void None %void_func\n" +
8641 "%main_lab = OpLabel\n" +
8642 "%2 = OpVariable %_ptr_v4double Function\n" +
8643 "%3 = OpVariable %_ptr_v4double Function\n" +
8644 "%4 = OpVariable %_ptr_v4double Function\n" +
8645 "%5 = OpLoad %v4double %2\n" +
8646 "%6 = OpLoad %v4double %3\n" +
8647 "%7 = OpLoad %v4double %4\n" +
8648 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8649 "%9 = OpVectorShuffle %v4double %8 %7 1 0 5 3\n" +
8650 "OpReturn\n" +
8651 "OpFunctionEnd",
8652 9, true),
8653 // Test case 10: Replace unused operand with null.
8654 InstructionFoldingCase<bool>(
8655 Header() +
8656 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8657 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8658 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
8659 "; CHECK: OpVectorShuffle\n" +
8660 "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %7 4 2 5 3\n" +
8661 "; CHECK: OpReturn\n" +
8662 "%main = OpFunction %void None %void_func\n" +
8663 "%main_lab = OpLabel\n" +
8664 "%2 = OpVariable %_ptr_v4double Function\n" +
8665 "%3 = OpVariable %_ptr_v4double Function\n" +
8666 "%4 = OpVariable %_ptr_v4double Function\n" +
8667 "%5 = OpLoad %v4double %2\n" +
8668 "%6 = OpLoad %v4double %3\n" +
8669 "%7 = OpLoad %v4double %4\n" +
8670 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8671 "%9 = OpVectorShuffle %v4double %8 %7 4 2 5 3\n" +
8672 "OpReturn\n" +
8673 "OpFunctionEnd",
8674 9, true),
8675 // Test case 11: Replace unused operand with null.
8676 InstructionFoldingCase<bool>(
8677 Header() +
8678 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8679 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8680 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
8681 "; CHECK: OpVectorShuffle\n" +
8682 "; CHECK: OpVectorShuffle {{%\\w+}} [[null]] %5 2 2 5 5\n" +
8683 "; CHECK: OpReturn\n" +
8684 "%main = OpFunction %void None %void_func\n" +
8685 "%main_lab = OpLabel\n" +
8686 "%2 = OpVariable %_ptr_v4double Function\n" +
8687 "%3 = OpVariable %_ptr_v4double Function\n" +
8688 "%5 = OpLoad %v4double %2\n" +
8689 "%6 = OpLoad %v4double %3\n" +
8690 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8691 "%9 = OpVectorShuffle %v4double %8 %8 2 2 3 3\n" +
8692 "OpReturn\n" +
8693 "OpFunctionEnd",
8694 9, true),
8695 // Test case 12: Replace unused operand with null.
8696 InstructionFoldingCase<bool>(
8697 Header() +
8698 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8699 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8700 "; CHECK: [[null:%\\w+]] = OpConstantNull [[v4double]]\n" +
8701 "; CHECK: OpVectorShuffle\n" +
8702 "; CHECK: OpVectorShuffle {{%\\w+}} %7 [[null]] 2 0 1 3\n" +
8703 "; CHECK: OpReturn\n" +
8704 "%main = OpFunction %void None %void_func\n" +
8705 "%main_lab = OpLabel\n" +
8706 "%2 = OpVariable %_ptr_v4double Function\n" +
8707 "%3 = OpVariable %_ptr_v4double Function\n" +
8708 "%4 = OpVariable %_ptr_v4double Function\n" +
8709 "%5 = OpLoad %v4double %2\n" +
8710 "%6 = OpLoad %v4double %3\n" +
8711 "%7 = OpLoad %v4double %4\n" +
8712 "%8 = OpVectorShuffle %v2double %5 %5 0 3\n" +
8713 "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 3\n" +
8714 "OpReturn\n" +
8715 "OpFunctionEnd",
8716 9, true),
8717 // Test case 13: Shuffle with undef literal.
8718 InstructionFoldingCase<bool>(
8719 Header() +
8720 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8721 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8722 "; CHECK: OpVectorShuffle\n" +
8723 "; CHECK: OpVectorShuffle {{%\\w+}} %7 {{%\\w+}} 2 0 1 4294967295\n" +
8724 "; CHECK: OpReturn\n" +
8725 "%main = OpFunction %void None %void_func\n" +
8726 "%main_lab = OpLabel\n" +
8727 "%2 = OpVariable %_ptr_v4double Function\n" +
8728 "%3 = OpVariable %_ptr_v4double Function\n" +
8729 "%4 = OpVariable %_ptr_v4double Function\n" +
8730 "%5 = OpLoad %v4double %2\n" +
8731 "%6 = OpLoad %v4double %3\n" +
8732 "%7 = OpLoad %v4double %4\n" +
8733 "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
8734 "%9 = OpVectorShuffle %v4double %7 %8 2 0 1 4294967295\n" +
8735 "OpReturn\n" +
8736 "OpFunctionEnd",
8737 9, true),
8738 // Test case 14: Shuffle with undef literal and change size of first input vector.
8739 InstructionFoldingCase<bool>(
8740 Header() +
8741 "; CHECK: [[double:%\\w+]] = OpTypeFloat 64\n" +
8742 "; CHECK: [[v4double:%\\w+]] = OpTypeVector [[double]] 2\n" +
8743 "; CHECK: OpVectorShuffle\n" +
8744 "; CHECK: OpVectorShuffle {{%\\w+}} %5 %7 0 1 4 4294967295\n" +
8745 "; CHECK: OpReturn\n" +
8746 "%main = OpFunction %void None %void_func\n" +
8747 "%main_lab = OpLabel\n" +
8748 "%2 = OpVariable %_ptr_v4double Function\n" +
8749 "%3 = OpVariable %_ptr_v4double Function\n" +
8750 "%4 = OpVariable %_ptr_v4double Function\n" +
8751 "%5 = OpLoad %v4double %2\n" +
8752 "%6 = OpLoad %v4double %3\n" +
8753 "%7 = OpLoad %v4double %4\n" +
8754 "%8 = OpVectorShuffle %v2double %5 %5 0 1\n" +
8755 "%9 = OpVectorShuffle %v4double %8 %7 0 1 2 4294967295\n" +
8756 "OpReturn\n" +
8757 "OpFunctionEnd",
8758 9, true)
8759 ));
8760
8761 using EntryPointFoldingTest =
8762 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8763
TEST_P(EntryPointFoldingTest,Case)8764 TEST_P(EntryPointFoldingTest, Case) {
8765 const auto& tc = GetParam();
8766
8767 // Build module.
8768 std::unique_ptr<IRContext> context =
8769 BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body,
8770 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
8771 ASSERT_NE(nullptr, context);
8772
8773 // Find the first entry point. That is the instruction we want to fold.
8774 Instruction* inst = nullptr;
8775 ASSERT_FALSE(context->module()->entry_points().empty());
8776 inst = &*context->module()->entry_points().begin();
8777 assert(inst && "Invalid test. Could not find entry point instruction to fold.");
8778 std::unique_ptr<Instruction> original_inst(inst->Clone(context.get()));
8779 bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
8780 EXPECT_EQ(succeeded, tc.expected_result);
8781 if (succeeded) {
8782 Match(tc.test_body, context.get());
8783 }
8784 }
8785
8786 INSTANTIATE_TEST_SUITE_P(OpEntryPointFoldingTest, EntryPointFoldingTest,
8787 ::testing::Values(
8788 // Test case 0: Basic test 1
8789 InstructionFoldingCase<bool>(std::string() +
8790 "; CHECK: OpEntryPoint Fragment %2 \"main\" %3\n" +
8791 "OpCapability Shader\n" +
8792 "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
8793 "OpMemoryModel Logical GLSL450\n" +
8794 "OpEntryPoint Fragment %2 \"main\" %3 %3 %3\n" +
8795 "OpExecutionMode %2 OriginUpperLeft\n" +
8796 "OpSource GLSL 430\n" +
8797 "OpDecorate %3 Location 0\n" +
8798 "%void = OpTypeVoid\n" +
8799 "%5 = OpTypeFunction %void\n" +
8800 "%float = OpTypeFloat 32\n" +
8801 "%v4float = OpTypeVector %float 4\n" +
8802 "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
8803 "%3 = OpVariable %_ptr_Output_v4float Output\n" +
8804 "%int = OpTypeInt 32 1\n" +
8805 "%int_0 = OpConstant %int 0\n" +
8806 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
8807 "%2 = OpFunction %void None %5\n" +
8808 "%12 = OpLabel\n" +
8809 "OpReturn\n" +
8810 "OpFunctionEnd\n",
8811 9, true),
8812 InstructionFoldingCase<bool>(std::string() +
8813 "; CHECK: OpEntryPoint Fragment %2 \"main\" %3 %4\n" +
8814 "OpCapability Shader\n" +
8815 "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
8816 "OpMemoryModel Logical GLSL450\n" +
8817 "OpEntryPoint Fragment %2 \"main\" %3 %4 %3\n" +
8818 "OpExecutionMode %2 OriginUpperLeft\n" +
8819 "OpSource GLSL 430\n" +
8820 "OpDecorate %3 Location 0\n" +
8821 "%void = OpTypeVoid\n" +
8822 "%5 = OpTypeFunction %void\n" +
8823 "%float = OpTypeFloat 32\n" +
8824 "%v4float = OpTypeVector %float 4\n" +
8825 "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
8826 "%3 = OpVariable %_ptr_Output_v4float Output\n" +
8827 "%4 = OpVariable %_ptr_Output_v4float Output\n" +
8828 "%int = OpTypeInt 32 1\n" +
8829 "%int_0 = OpConstant %int 0\n" +
8830 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
8831 "%2 = OpFunction %void None %5\n" +
8832 "%12 = OpLabel\n" +
8833 "OpReturn\n" +
8834 "OpFunctionEnd\n",
8835 9, true),
8836 InstructionFoldingCase<bool>(std::string() +
8837 "; CHECK: OpEntryPoint Fragment %2 \"main\" %4 %3\n" +
8838 "OpCapability Shader\n" +
8839 "%1 = OpExtInstImport \"GLSL.std.450\"\n" +
8840 "OpMemoryModel Logical GLSL450\n" +
8841 "OpEntryPoint Fragment %2 \"main\" %4 %4 %3\n" +
8842 "OpExecutionMode %2 OriginUpperLeft\n" +
8843 "OpSource GLSL 430\n" +
8844 "OpDecorate %3 Location 0\n" +
8845 "%void = OpTypeVoid\n" +
8846 "%5 = OpTypeFunction %void\n" +
8847 "%float = OpTypeFloat 32\n" +
8848 "%v4float = OpTypeVector %float 4\n" +
8849 "%_ptr_Output_v4float = OpTypePointer Output %v4float\n" +
8850 "%3 = OpVariable %_ptr_Output_v4float Output\n" +
8851 "%4 = OpVariable %_ptr_Output_v4float Output\n" +
8852 "%int = OpTypeInt 32 1\n" +
8853 "%int_0 = OpConstant %int 0\n" +
8854 "%_ptr_PushConstant_v4float = OpTypePointer PushConstant %v4float\n" +
8855 "%2 = OpFunction %void None %5\n" +
8856 "%12 = OpLabel\n" +
8857 "OpReturn\n" +
8858 "OpFunctionEnd\n",
8859 9, true)
8860 ));
8861
8862 using SPV14FoldingTest =
8863 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8864
TEST_P(SPV14FoldingTest,Case)8865 TEST_P(SPV14FoldingTest, Case) {
8866 const auto& tc = GetParam();
8867
8868 std::unique_ptr<IRContext> context;
8869 Instruction* inst;
8870 std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold,SPV_ENV_UNIVERSAL_1_4);
8871
8872 EXPECT_EQ(inst != nullptr, tc.expected_result);
8873 if (inst != nullptr) {
8874 Match(tc.test_body, context.get());
8875 }
8876 }
8877
8878 INSTANTIATE_TEST_SUITE_P(SPV14FoldingTest, SPV14FoldingTest,
8879 ::testing::Values(
8880 // Test case 0: select vectors with scalar condition.
8881 InstructionFoldingCase<bool>(std::string() +
8882 "; CHECK-NOT: OpSelect\n" +
8883 "; CHECK: %3 = OpCopyObject {{%\\w+}} %1\n" +
8884 "OpCapability Shader\n" +
8885 "OpCapability Linkage\n" +
8886 "%void = OpTypeVoid\n" +
8887 "%bool = OpTypeBool\n" +
8888 "%true = OpConstantTrue %bool\n" +
8889 "%int = OpTypeInt 32 0\n" +
8890 "%int4 = OpTypeVector %int 4\n" +
8891 "%int_0 = OpConstant %int 0\n" +
8892 "%int_1 = OpConstant %int 1\n" +
8893 "%1 = OpUndef %int4\n" +
8894 "%2 = OpUndef %int4\n" +
8895 "%void_fn = OpTypeFunction %void\n" +
8896 "%func = OpFunction %void None %void_fn\n" +
8897 "%entry = OpLabel\n" +
8898 "%3 = OpSelect %int4 %true %1 %2\n" +
8899 "OpReturn\n" +
8900 "OpFunctionEnd\n"
8901 ,
8902 3, true),
8903 // Test case 1: select struct with scalar condition.
8904 InstructionFoldingCase<bool>(std::string() +
8905 "; CHECK-NOT: OpSelect\n" +
8906 "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
8907 "OpCapability Shader\n" +
8908 "OpCapability Linkage\n" +
8909 "%void = OpTypeVoid\n" +
8910 "%bool = OpTypeBool\n" +
8911 "%true = OpConstantFalse %bool\n" +
8912 "%int = OpTypeInt 32 0\n" +
8913 "%struct = OpTypeStruct %int %int %int %int\n" +
8914 "%int_0 = OpConstant %int 0\n" +
8915 "%int_1 = OpConstant %int 1\n" +
8916 "%1 = OpUndef %struct\n" +
8917 "%2 = OpUndef %struct\n" +
8918 "%void_fn = OpTypeFunction %void\n" +
8919 "%func = OpFunction %void None %void_fn\n" +
8920 "%entry = OpLabel\n" +
8921 "%3 = OpSelect %struct %true %1 %2\n" +
8922 "OpReturn\n" +
8923 "OpFunctionEnd\n"
8924 ,
8925 3, true),
8926 // Test case 1: select array with scalar condition.
8927 InstructionFoldingCase<bool>(std::string() +
8928 "; CHECK-NOT: OpSelect\n" +
8929 "; CHECK: %3 = OpCopyObject {{%\\w+}} %2\n" +
8930 "OpCapability Shader\n" +
8931 "OpCapability Linkage\n" +
8932 "%void = OpTypeVoid\n" +
8933 "%bool = OpTypeBool\n" +
8934 "%true = OpConstantFalse %bool\n" +
8935 "%int = OpTypeInt 32 0\n" +
8936 "%int_0 = OpConstant %int 0\n" +
8937 "%int_1 = OpConstant %int 1\n" +
8938 "%int_4 = OpConstant %int 4\n" +
8939 "%array = OpTypeStruct %int %int %int %int\n" +
8940 "%1 = OpUndef %array\n" +
8941 "%2 = OpUndef %array\n" +
8942 "%void_fn = OpTypeFunction %void\n" +
8943 "%func = OpFunction %void None %void_fn\n" +
8944 "%entry = OpLabel\n" +
8945 "%3 = OpSelect %array %true %1 %2\n" +
8946 "OpReturn\n" +
8947 "OpFunctionEnd\n"
8948 ,
8949 3, true)
8950 ));
8951
FloatControlsHeader(const std::string & capabilities)8952 std::string FloatControlsHeader(const std::string& capabilities) {
8953 std::string header = R"(
8954 OpCapability Shader
8955 )" + capabilities + R"(
8956 %void = OpTypeVoid
8957 %float = OpTypeFloat 32
8958 %float_0 = OpConstant %float 0
8959 %float_1 = OpConstant %float 1
8960 %void_fn = OpTypeFunction %void
8961 %func = OpFunction %void None %void_fn
8962 %entry = OpLabel
8963 )";
8964
8965 return header;
8966 }
8967
8968 using FloatControlsFoldingTest =
8969 ::testing::TestWithParam<InstructionFoldingCase<bool>>;
8970
TEST_P(FloatControlsFoldingTest,Case)8971 TEST_P(FloatControlsFoldingTest, Case) {
8972 const auto& tc = GetParam();
8973
8974 std::unique_ptr<IRContext> context;
8975 Instruction* inst;
8976 std::tie(context, inst) = FoldInstruction(tc.test_body, tc.id_to_fold, SPV_ENV_UNIVERSAL_1_4);
8977
8978 EXPECT_EQ(inst != nullptr, tc.expected_result);
8979 if (inst != nullptr) {
8980 Match(tc.test_body, context.get());
8981 }
8982 }
8983
8984 INSTANTIATE_TEST_SUITE_P(FloatControlsFoldingTest, FloatControlsFoldingTest,
8985 ::testing::Values(
8986 // Test case 0: no folding with DenormPreserve
8987 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormPreserve") +
8988 "%1 = OpFAdd %float %float_0 %float_1\n" +
8989 "OpReturn\n" +
8990 "OpFunctionEnd\n"
8991 ,
8992 1, false),
8993 // Test case 1: no folding with DenormFlushToZero
8994 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability DenormFlushToZero") +
8995 "%1 = OpFAdd %float %float_0 %float_1\n" +
8996 "OpReturn\n" +
8997 "OpFunctionEnd\n"
8998 ,
8999 1, false),
9000 // Test case 2: no folding with SignedZeroInfNanPreserve
9001 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability SignedZeroInfNanPreserve") +
9002 "%1 = OpFAdd %float %float_0 %float_1\n" +
9003 "OpReturn\n" +
9004 "OpFunctionEnd\n"
9005 ,
9006 1, false),
9007 // Test case 3: no folding with RoundingModeRTE
9008 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTE") +
9009 "%1 = OpFAdd %float %float_0 %float_1\n" +
9010 "OpReturn\n" +
9011 "OpFunctionEnd\n"
9012 ,
9013 1, false),
9014 // Test case 4: no folding with RoundingModeRTZ
9015 InstructionFoldingCase<bool>(FloatControlsHeader("OpCapability RoundingModeRTZ") +
9016 "%1 = OpFAdd %float %float_0 %float_1\n" +
9017 "OpReturn\n" +
9018 "OpFunctionEnd\n"
9019 ,
9020 1, false)
9021 ));
9022
ImageOperandsTestBody(const std::string & image_instruction)9023 std::string ImageOperandsTestBody(const std::string& image_instruction) {
9024 std::string body = R"(
9025 OpCapability Shader
9026 OpCapability ImageGatherExtended
9027 OpMemoryModel Logical GLSL450
9028 OpEntryPoint Fragment %main "main"
9029 OpExecutionMode %main OriginUpperLeft
9030 OpDecorate %Texture DescriptorSet 0
9031 OpDecorate %Texture Binding 0
9032 %int = OpTypeInt 32 1
9033 %int_n1 = OpConstant %int -1
9034 %5 = OpConstant %int 0
9035 %float = OpTypeFloat 32
9036 %float_0 = OpConstant %float 0
9037 %type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown
9038 %type_sampled_image = OpTypeSampledImage %type_2d_image
9039 %type_sampler = OpTypeSampler
9040 %_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler
9041 %_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image
9042 %_ptr_int = OpTypePointer Function %int
9043 %v2int = OpTypeVector %int 2
9044 %10 = OpTypeVector %float 4
9045 %void = OpTypeVoid
9046 %22 = OpTypeFunction %void
9047 %v2float = OpTypeVector %float 2
9048 %v3int = OpTypeVector %int 3
9049 %Texture = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant
9050 %gSampler = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant
9051 %110 = OpConstantComposite %v2int %5 %5
9052 %101 = OpConstantComposite %v2int %int_n1 %int_n1
9053 %20 = OpConstantComposite %v2float %float_0 %float_0
9054 %main = OpFunction %void None %22
9055 %23 = OpLabel
9056 %var = OpVariable %_ptr_int Function
9057 %88 = OpLoad %type_2d_image %Texture
9058 %val = OpLoad %int %var
9059 %sampler = OpLoad %type_sampler %gSampler
9060 %26 = OpSampledImage %type_sampled_image %88 %sampler
9061 )" + image_instruction + R"(
9062 OpReturn
9063 OpFunctionEnd
9064 )";
9065
9066 return body;
9067 }
9068
9069 INSTANTIATE_TEST_SUITE_P(ImageOperandsBitmaskFoldingTest, MatchingInstructionWithNoResultFoldingTest,
9070 ::testing::Values(
9071 // Test case 0: OpImageFetch without Offset
9072 InstructionFoldingCase<bool>(ImageOperandsTestBody(
9073 "%89 = OpImageFetch %10 %88 %101 Lod %5 \n")
9074 , 89, false),
9075 // Test case 1: OpImageFetch with non-const offset
9076 InstructionFoldingCase<bool>(ImageOperandsTestBody(
9077 "%89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %val \n")
9078 , 89, false),
9079 // Test case 2: OpImageFetch with Lod and Offset
9080 InstructionFoldingCase<bool>(ImageOperandsTestBody(
9081 " %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %101 \n"
9082 "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod|ConstOffset %5 %101 \n")
9083 , 89, true),
9084 // Test case 3: OpImageFetch with Bias and Offset
9085 InstructionFoldingCase<bool>(ImageOperandsTestBody(
9086 " %89 = OpImageFetch %10 %88 %101 Bias|Offset %5 %101 \n"
9087 "; CHECK: %89 = OpImageFetch %10 %88 %101 Bias|ConstOffset %5 %101 \n")
9088 , 89, true),
9089 // Test case 4: OpImageFetch with Grad and Offset.
9090 // Grad adds 2 operands to the instruction.
9091 InstructionFoldingCase<bool>(ImageOperandsTestBody(
9092 " %89 = OpImageFetch %10 %88 %101 Grad|Offset %5 %5 %101 \n"
9093 "; CHECK: %89 = OpImageFetch %10 %88 %101 Grad|ConstOffset %5 %5 %101 \n")
9094 , 89, true),
9095 // Test case 5: OpImageFetch with Offset and MinLod.
9096 // This is an example of a case where the bitmask bit-offset is larger than
9097 // that of the Offset.
9098 InstructionFoldingCase<bool>(ImageOperandsTestBody(
9099 " %89 = OpImageFetch %10 %88 %101 Offset|MinLod %101 %5 \n"
9100 "; CHECK: %89 = OpImageFetch %10 %88 %101 ConstOffset|MinLod %101 %5 \n")
9101 , 89, true),
9102 // Test case 6: OpImageGather with constant Offset
9103 InstructionFoldingCase<bool>(ImageOperandsTestBody(
9104 " %89 = OpImageGather %10 %26 %20 %5 Offset %101 \n"
9105 "; CHECK: %89 = OpImageGather %10 %26 %20 %5 ConstOffset %101 \n")
9106 , 89, true),
9107 // Test case 7: OpImageWrite with constant Offset
9108 InstructionFoldingCase<bool>(ImageOperandsTestBody(
9109 " OpImageWrite %88 %5 %101 Offset %101 \n"
9110 "; CHECK: OpImageWrite %88 %5 %101 ConstOffset %101 \n")
9111 , 0 /* No result-id */, true),
9112 // Test case 8: OpImageFetch with zero constant Offset
9113 InstructionFoldingCase<bool>(ImageOperandsTestBody(
9114 " %89 = OpImageFetch %10 %88 %101 Lod|Offset %5 %110 \n"
9115 "; CHECK: %89 = OpImageFetch %10 %88 %101 Lod %5 \n")
9116 , 89, true)
9117 ));
9118
9119 } // namespace
9120 } // namespace opt
9121 } // namespace spvtools
9122