HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Android 10
|
10.0.0_r6
下载
查看原文件
收藏
根目录
external
swiftshader
third_party
SPIRV-Tools
test
opt
fold_test.cpp
// Copyright (c) 2016 Google Inc. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include
#include
#include
#include
#include
#include "effcee/effcee.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "source/opt/build_module.h" #include "source/opt/def_use_manager.h" #include "source/opt/fold.h" #include "source/opt/ir_context.h" #include "source/opt/module.h" #include "spirv-tools/libspirv.hpp" #include "test/opt/pass_utils.h" namespace spvtools { namespace opt { namespace { using ::testing::Contains; std::string Disassemble(const std::string& original, IRContext* context, uint32_t disassemble_options = 0) { std::vector
optimized_bin; context->module()->ToBinary(&optimized_bin, true); spv_target_env target_env = SPV_ENV_UNIVERSAL_1_2; SpirvTools tools(target_env); std::string optimized_asm; EXPECT_TRUE( tools.Disassemble(optimized_bin, &optimized_asm, disassemble_options)) << "Disassembling failed for shader:\n" << original << std::endl; return optimized_asm; } void Match(const std::string& original, IRContext* context, uint32_t disassemble_options = 0) { std::string disassembly = Disassemble(original, context, disassemble_options); auto match_result = effcee::Match(disassembly, original); EXPECT_EQ(effcee::Result::Status::Ok, match_result.status()) << match_result.message() << "\nChecking result:\n" << disassembly; } template
struct InstructionFoldingCase { InstructionFoldingCase(const std::string& tb, uint32_t id, ResultType result) : test_body(tb), id_to_fold(id), expected_result(result) {} std::string test_body; uint32_t id_to_fold; ResultType expected_result; }; using IntegerInstructionFoldingTest = ::testing::TestWithParam
>; TEST_P(IntegerInstructionFoldingTest, Case) { const auto& tc = GetParam(); // Build module. std::unique_ptr
context = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); ASSERT_NE(nullptr, context); // Fold the instruction to test. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold); bool succeeded = context->get_instruction_folder().FoldInstruction(inst); // Make sure the instruction folded as expected. EXPECT_TRUE(succeeded); if (inst != nullptr) { EXPECT_EQ(inst->opcode(), SpvOpCopyObject); inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0)); EXPECT_EQ(inst->opcode(), SpvOpConstant); analysis::ConstantManager* const_mrg = context->get_constant_mgr(); const analysis::IntConstant* result = const_mrg->GetConstantFromInst(inst)->AsIntConstant(); EXPECT_NE(result, nullptr); if (result != nullptr) { EXPECT_EQ(result->GetU32BitValue(), tc.expected_result); } } } // Returns a common SPIR-V header for all of the test that follow. #define INT_0_ID 100 #define TRUE_ID 101 #define VEC2_0_ID 102 #define INT_7_ID 103 #define FLOAT_0_ID 104 #define DOUBLE_0_ID 105 #define VEC4_0_ID 106 #define DVEC4_0_ID 106 #define HALF_0_ID 108 const std::string& Header() { static const std::string header = R"(OpCapability Shader OpCapability Float16 OpCapability Float64 OpCapability Int16 OpCapability Int64 %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %main "main" OpExecutionMode %main OriginUpperLeft OpSource GLSL 140 OpName %main "main" %void = OpTypeVoid %void_func = OpTypeFunction %void %bool = OpTypeBool %float = OpTypeFloat 32 %double = OpTypeFloat 64 %half = OpTypeFloat 16 %101 = OpConstantTrue %bool ; Need a def with an numerical id to define id maps. %true = OpConstantTrue %bool %false = OpConstantFalse %bool %bool_null = OpConstantNull %bool %short = OpTypeInt 16 1 %int = OpTypeInt 32 1 %long = OpTypeInt 64 1 %uint = OpTypeInt 32 0 %v2int = OpTypeVector %int 2 %v4int = OpTypeVector %int 4 %v4float = OpTypeVector %float 4 %v4double = OpTypeVector %double 4 %v2float = OpTypeVector %float 2 %v2double = OpTypeVector %double 2 %v2bool = OpTypeVector %bool 2 %struct_v2int_int_int = OpTypeStruct %v2int %int %int %_ptr_int = OpTypePointer Function %int %_ptr_uint = OpTypePointer Function %uint %_ptr_bool = OpTypePointer Function %bool %_ptr_float = OpTypePointer Function %float %_ptr_double = OpTypePointer Function %double %_ptr_half = OpTypePointer Function %half %_ptr_long = OpTypePointer Function %long %_ptr_v2int = OpTypePointer Function %v2int %_ptr_v4int = OpTypePointer Function %v4int %_ptr_v4float = OpTypePointer Function %v4float %_ptr_v4double = OpTypePointer Function %v4double %_ptr_struct_v2int_int_int = OpTypePointer Function %struct_v2int_int_int %_ptr_v2float = OpTypePointer Function %v2float %_ptr_v2double = OpTypePointer Function %v2double %short_0 = OpConstant %short 0 %short_2 = OpConstant %short 2 %short_3 = OpConstant %short 3 %100 = OpConstant %int 0 ; Need a def with an numerical id to define id maps. %103 = OpConstant %int 7 ; Need a def with an numerical id to define id maps. %int_0 = OpConstant %int 0 %int_1 = OpConstant %int 1 %int_2 = OpConstant %int 2 %int_3 = OpConstant %int 3 %int_4 = OpConstant %int 4 %int_n24 = OpConstant %int -24 %int_min = OpConstant %int -2147483648 %int_max = OpConstant %int 2147483647 %long_0 = OpConstant %long 0 %long_2 = OpConstant %long 2 %long_3 = OpConstant %long 3 %uint_0 = OpConstant %uint 0 %uint_1 = OpConstant %uint 1 %uint_2 = OpConstant %uint 2 %uint_3 = OpConstant %uint 3 %uint_4 = OpConstant %uint 4 %uint_32 = OpConstant %uint 32 %uint_42 = OpConstant %uint 42 %uint_max = OpConstant %uint 4294967295 %v2int_undef = OpUndef %v2int %v2int_0_0 = OpConstantComposite %v2int %int_0 %int_0 %v2int_1_0 = OpConstantComposite %v2int %int_1 %int_0 %v2int_2_2 = OpConstantComposite %v2int %int_2 %int_2 %v2int_2_3 = OpConstantComposite %v2int %int_2 %int_3 %v2int_3_2 = OpConstantComposite %v2int %int_3 %int_2 %v2int_4_4 = OpConstantComposite %v2int %int_4 %int_4 %v2bool_null = OpConstantNull %v2bool %v2bool_true_false = OpConstantComposite %v2bool %true %false %v2bool_false_true = OpConstantComposite %v2bool %false %true %struct_v2int_int_int_null = OpConstantNull %struct_v2int_int_int %v2int_null = OpConstantNull %v2int %102 = OpConstantComposite %v2int %103 %103 %v4int_0_0_0_0 = OpConstantComposite %v4int %int_0 %int_0 %int_0 %int_0 %struct_undef_0_0 = OpConstantComposite %struct_v2int_int_int %v2int_undef %int_0 %int_0 %float_n1 = OpConstant %float -1 %104 = OpConstant %float 0 ; Need a def with an numerical id to define id maps. %float_null = OpConstantNull %float %float_0 = OpConstant %float 0 %float_1 = OpConstant %float 1 %float_2 = OpConstant %float 2 %float_3 = OpConstant %float 3 %float_4 = OpConstant %float 4 %float_0p5 = OpConstant %float 0.5 %v2float_0_0 = OpConstantComposite %v2float %float_0 %float_0 %v2float_2_2 = OpConstantComposite %v2float %float_2 %float_2 %v2float_2_3 = OpConstantComposite %v2float %float_2 %float_3 %v2float_3_2 = OpConstantComposite %v2float %float_3 %float_2 %v2float_4_4 = OpConstantComposite %v2float %float_4 %float_4 %v2float_2_0p5 = OpConstantComposite %v2float %float_2 %float_0p5 %v2float_null = OpConstantNull %v2float %double_n1 = OpConstant %double -1 %105 = OpConstant %double 0 ; Need a def with an numerical id to define id maps. %double_null = OpConstantNull %double %double_0 = OpConstant %double 0 %double_1 = OpConstant %double 1 %double_2 = OpConstant %double 2 %double_3 = OpConstant %double 3 %double_4 = OpConstant %double 4 %double_0p5 = OpConstant %double 0.5 %v2double_0_0 = OpConstantComposite %v2double %double_0 %double_0 %v2double_2_2 = OpConstantComposite %v2double %double_2 %double_2 %v2double_2_3 = OpConstantComposite %v2double %double_2 %double_3 %v2double_3_2 = OpConstantComposite %v2double %double_3 %double_2 %v2double_4_4 = OpConstantComposite %v2double %double_4 %double_4 %v2double_2_0p5 = OpConstantComposite %v2double %double_2 %double_0p5 %v2double_null = OpConstantNull %v2double %108 = OpConstant %half 0 %half_1 = OpConstant %half 1 %106 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 %v4float_0_0_0_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 %v4float_0_0_0_1 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_1 %v4float_0_1_0_0 = OpConstantComposite %v4float %float_0 %float_1 %float_null %float_0 %v4float_1_1_1_1 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 %107 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0 %v4double_0_0_0_0 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_0 %v4double_0_0_0_1 = OpConstantComposite %v4double %double_0 %double_0 %double_0 %double_1 %v4double_0_1_0_0 = OpConstantComposite %v4double %double_0 %double_1 %double_null %double_0 %v4double_1_1_1_1 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_1 %v4double_1_1_1_0p5 = OpConstantComposite %v4double %double_1 %double_1 %double_1 %double_0p5 %v4double_null = OpConstantNull %v4double %v4float_n1_2_1_3 = OpConstantComposite %v4float %float_n1 %float_2 %float_1 %float_3 )"; return header; } // Returns the header with definitions of float NaN and double NaN. Since FC // "; CHECK: [[double_n0:%\\w+]] = OpConstant [[double]] -0\n" finds // %double_nan = OpConstant %double -0x1.8p+1024 instead of // %double_n0 = OpConstant %double -0, // we separates those definitions from Header(). const std::string& HeaderWithNaN() { static const std::string headerWithNaN = Header() + R"(%float_nan = OpConstant %float -0x1.8p+128 %double_nan = OpConstant %double -0x1.8p+1024 )"; return headerWithNaN; } // clang-format off INSTANTIATE_TEST_CASE_P(TestCase, IntegerInstructionFoldingTest, ::testing::Values( // Test case 0: fold 0*n InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpIMul %int %int_0 %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 1: fold n*0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpIMul %int %load %int_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 2: fold 0/n (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSDiv %int %int_0 %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 3: fold n/0 (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSDiv %int %load %int_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 4: fold 0/n (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpUDiv %uint %uint_0 %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 5: fold n/0 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSDiv %int %load %int_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 6: fold 0 remainder n InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSRem %int %int_0 %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 7: fold n remainder 0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSRem %int %load %int_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 8: fold 0%n (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSMod %int %int_0 %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 9: fold n%0 (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSMod %int %load %int_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 10: fold 0%n (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpUMod %uint %uint_0 %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 11: fold n%0 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpUMod %uint %load %uint_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 12: fold n << 32 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpShiftLeftLogical %uint %load %uint_32\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 13: fold n >> 32 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpShiftRightLogical %uint %load %uint_32\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 14: fold n | 0xFFFFFFFF InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpBitwiseOr %uint %load %uint_max\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0xFFFFFFFF), // Test case 15: fold 0xFFFFFFFF | n InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpBitwiseOr %uint %uint_max %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0xFFFFFFFF), // Test case 16: fold n & 0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpBitwiseAnd %uint %load %uint_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 17: fold 1/0 (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpSDiv %int %int_1 %int_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 18: fold 1/0 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpUDiv %uint %uint_1 %uint_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 19: fold OpSRem 1 0 (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpSRem %int %int_1 %int_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 20: fold 1%0 (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpSMod %int %int_1 %int_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 21: fold 1%0 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpUMod %uint %uint_1 %uint_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 22: fold unsigned n >> 42 (undefined, so set to zero). InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpShiftRightLogical %uint %load %uint_42\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 23: fold signed n >> 42 (undefined, so set to zero). InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpShiftRightLogical %int %load %uint_42\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 24: fold n << 42 (undefined, so set to zero). InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpShiftLeftLogical %int %load %uint_42\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 25: fold -24 >> 32 (defined as -1) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpShiftRightArithmetic %int %int_n24 %uint_32\n" + "OpReturn\n" + "OpFunctionEnd", 2, -1), // Test case 26: fold 2 >> 32 (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpShiftRightArithmetic %int %int_2 %uint_32\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 27: fold 2 >> 32 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpShiftRightLogical %int %int_2 %uint_32\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 28: fold 2 << 32 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpShiftLeftLogical %int %int_2 %uint_32\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 29: fold -INT_MIN InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpSNegate %int %int_min\n" + "OpReturn\n" + "OpFunctionEnd", 2, std::numeric_limits
::min()) )); // clang-format on using IntVectorInstructionFoldingTest = ::testing::TestWithParam
>>; TEST_P(IntVectorInstructionFoldingTest, Case) { const auto& tc = GetParam(); // Build module. std::unique_ptr
context = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); ASSERT_NE(nullptr, context); // Fold the instruction to test. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold); SpvOp original_opcode = inst->opcode(); bool succeeded = context->get_instruction_folder().FoldInstruction(inst); // Make sure the instruction folded as expected. EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode); if (succeeded && inst != nullptr) { EXPECT_EQ(inst->opcode(), SpvOpCopyObject); inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0)); std::vector
opcodes = {SpvOpConstantComposite}; EXPECT_THAT(opcodes, Contains(inst->opcode())); analysis::ConstantManager* const_mrg = context->get_constant_mgr(); const analysis::Constant* result = const_mrg->GetConstantFromInst(inst); EXPECT_NE(result, nullptr); if (result != nullptr) { const std::vector
& componenets = result->AsVectorConstant()->GetComponents(); EXPECT_EQ(componenets.size(), tc.expected_result.size()); for (size_t i = 0; i < componenets.size(); i++) { EXPECT_EQ(tc.expected_result[i], componenets[i]->GetU32()); } } } } // clang-format off INSTANTIATE_TEST_CASE_P(TestCase, IntVectorInstructionFoldingTest, ::testing::Values( // Test case 0: fold 0*n InstructionFoldingCase
>( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpVectorShuffle %v2int %v2int_2_2 %v2int_2_3 0 3\n" + "OpReturn\n" + "OpFunctionEnd", 2, {2,3}), InstructionFoldingCase
>( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 3\n" + "OpReturn\n" + "OpFunctionEnd", 2, {0,3}), InstructionFoldingCase
>( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 4294967295 3\n" + "OpReturn\n" + "OpFunctionEnd", 2, {0,0}), InstructionFoldingCase
>( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpVectorShuffle %v2int %v2int_null %v2int_2_3 0 4294967295 \n" + "OpReturn\n" + "OpFunctionEnd", 2, {0,0}) )); // clang-format on using BooleanInstructionFoldingTest = ::testing::TestWithParam
>; TEST_P(BooleanInstructionFoldingTest, Case) { const auto& tc = GetParam(); // Build module. std::unique_ptr
context = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); ASSERT_NE(nullptr, context); // Fold the instruction to test. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold); bool succeeded = context->get_instruction_folder().FoldInstruction(inst); // Make sure the instruction folded as expected. EXPECT_TRUE(succeeded); if (inst != nullptr) { EXPECT_EQ(inst->opcode(), SpvOpCopyObject); inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0)); std::vector
bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse}; EXPECT_THAT(bool_opcodes, Contains(inst->opcode())); analysis::ConstantManager* const_mrg = context->get_constant_mgr(); const analysis::BoolConstant* result = const_mrg->GetConstantFromInst(inst)->AsBoolConstant(); EXPECT_NE(result, nullptr); if (result != nullptr) { EXPECT_EQ(result->value(), tc.expected_result); } } } // clang-format off INSTANTIATE_TEST_CASE_P(TestCase, BooleanInstructionFoldingTest, ::testing::Values( // Test case 0: fold true || n InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_bool Function\n" + "%load = OpLoad %bool %n\n" + "%2 = OpLogicalOr %bool %true %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 1: fold n || true InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_bool Function\n" + "%load = OpLoad %bool %n\n" + "%2 = OpLogicalOr %bool %load %true\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 2: fold false && n InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_bool Function\n" + "%load = OpLoad %bool %n\n" + "%2 = OpLogicalAnd %bool %false %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 3: fold n && false InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_bool Function\n" + "%load = OpLoad %bool %n\n" + "%2 = OpLogicalAnd %bool %load %false\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 4: fold n < 0 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpULessThan %bool %load %uint_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 5: fold UINT_MAX < n (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpULessThan %bool %uint_max %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 6: fold INT_MAX < n (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSLessThan %bool %int_max %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 7: fold n < INT_MIN (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSLessThan %bool %load %int_min\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 8: fold 0 > n (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpUGreaterThan %bool %uint_0 %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 9: fold n > UINT_MAX (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpUGreaterThan %bool %load %uint_max\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 10: fold n > INT_MAX (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSGreaterThan %bool %load %int_max\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 11: fold INT_MIN > n (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpSGreaterThan %bool %int_min %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 12: fold 0 <= n (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpULessThanEqual %bool %uint_0 %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 13: fold n <= UINT_MAX (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpULessThanEqual %bool %load %uint_max\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 14: fold INT_MIN <= n (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSLessThanEqual %bool %int_min %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 15: fold n <= INT_MAX (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSLessThanEqual %bool %load %int_max\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 16: fold n >= 0 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpUGreaterThanEqual %bool %load %uint_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 17: fold UINT_MAX >= n (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load = OpLoad %uint %n\n" + "%2 = OpUGreaterThanEqual %bool %uint_max %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 18: fold n >= INT_MIN (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSGreaterThanEqual %bool %load %int_min\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 19: fold INT_MAX >= n (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%2 = OpSGreaterThanEqual %bool %int_max %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, true) )); INSTANTIATE_TEST_CASE_P(FClampAndCmpLHS, BooleanInstructionFoldingTest, ::testing::Values( // Test case 0: fold 0.0 > clamp(n, 0.0, 1.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" + "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 1: fold 0.0 > clamp(n, -1.0, -1.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" + "%2 = OpFOrdGreaterThan %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 2: fold 0.0 >= clamp(n, 1, 2) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 3: fold 0.0 >= clamp(n, -1.0, 0.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" + "%2 = OpFOrdGreaterThanEqual %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 4: fold 0.0 <= clamp(n, 0.0, 1.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" + "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 5: fold 0.0 <= clamp(n, -1.0, -1.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" + "%2 = OpFOrdLessThanEqual %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 6: fold 0.0 < clamp(n, 1, 2) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 7: fold 0.0 < clamp(n, -1.0, 0.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" + "%2 = OpFOrdLessThan %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 8: fold 0.0 > clamp(n, 0.0, 1.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" + "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 9: fold 0.0 > clamp(n, -1.0, -1.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" + "%2 = OpFUnordGreaterThan %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 10: fold 0.0 >= clamp(n, 1, 2) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 11: fold 0.0 >= clamp(n, -1.0, 0.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" + "%2 = OpFUnordGreaterThanEqual %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 12: fold 0.0 <= clamp(n, 0.0, 1.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" + "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 13: fold 0.0 <= clamp(n, -1.0, -1.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_n1\n" + "%2 = OpFUnordLessThanEqual %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 14: fold 0.0 < clamp(n, 1, 2) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 15: fold 0.0 < clamp(n, -1.0, 0.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" + "%2 = OpFUnordLessThan %bool %float_0 %clamp\n" + "OpReturn\n" + "OpFunctionEnd", 2, false) )); INSTANTIATE_TEST_CASE_P(FClampAndCmpRHS, BooleanInstructionFoldingTest, ::testing::Values( // Test case 0: fold clamp(n, 0.0, 1.0) > 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" + "%2 = OpFOrdGreaterThan %bool %clamp %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 1: fold clamp(n, 1.0, 1.0) > 0.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" + "%2 = OpFOrdGreaterThan %bool %clamp %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 2: fold clamp(n, 1, 2) >= 0.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 3: fold clamp(n, 1.0, 2.0) >= 3.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFOrdGreaterThanEqual %bool %clamp %float_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 4: fold clamp(n, 0.0, 1.0) <= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" + "%2 = OpFOrdLessThanEqual %bool %clamp %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 5: fold clamp(n, 1.0, 2.0) <= 0.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFOrdLessThanEqual %bool %clamp %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 6: fold clamp(n, 1, 2) < 3 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFOrdLessThan %bool %clamp %float_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 7: fold clamp(n, -1.0, 0.0) < -1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" + "%2 = OpFOrdLessThan %bool %clamp %float_n1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 8: fold clamp(n, 0.0, 1.0) > 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" + "%2 = OpFUnordGreaterThan %bool %clamp %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 9: fold clamp(n, 1.0, 2.0) > 0.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFUnordGreaterThan %bool %clamp %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 10: fold clamp(n, 1, 2) >= 3.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 11: fold clamp(n, -1.0, 0.0) >= -1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" + "%2 = OpFUnordGreaterThanEqual %bool %clamp %float_n1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 12: fold clamp(n, 0.0, 1.0) <= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_0 %float_1\n" + "%2 = OpFUnordLessThanEqual %bool %clamp %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 13: fold clamp(n, 1.0, 1.0) <= 0.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_1\n" + "%2 = OpFUnordLessThanEqual %bool %clamp %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 14: fold clamp(n, 1, 2) < 3 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_1 %float_2\n" + "%2 = OpFUnordLessThan %bool %clamp %float_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 15: fold clamp(n, -1.0, 0.0) < -1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_float Function\n" + "%ld = OpLoad %float %n\n" + "%clamp = OpExtInst %float %1 FClamp %ld %float_n1 %float_0\n" + "%2 = OpFUnordLessThan %bool %clamp %float_n1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 16: fold clamp(n, -1.0, 0.0) < -1.0 (one test for double) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_double Function\n" + "%ld = OpLoad %double %n\n" + "%clamp = OpExtInst %double %1 FClamp %ld %double_n1 %double_0\n" + "%2 = OpFUnordLessThan %bool %clamp %double_n1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false) )); // clang-format on using FloatInstructionFoldingTest = ::testing::TestWithParam
>; TEST_P(FloatInstructionFoldingTest, Case) { const auto& tc = GetParam(); // Build module. std::unique_ptr
context = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); ASSERT_NE(nullptr, context); // Fold the instruction to test. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold); bool succeeded = context->get_instruction_folder().FoldInstruction(inst); // Make sure the instruction folded as expected. EXPECT_TRUE(succeeded); if (inst != nullptr) { EXPECT_EQ(inst->opcode(), SpvOpCopyObject); inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0)); EXPECT_EQ(inst->opcode(), SpvOpConstant); analysis::ConstantManager* const_mrg = context->get_constant_mgr(); const analysis::FloatConstant* result = const_mrg->GetConstantFromInst(inst)->AsFloatConstant(); EXPECT_NE(result, nullptr); if (result != nullptr) { EXPECT_EQ(result->GetFloatValue(), tc.expected_result); } } } // Not testing NaNs because there are no expectations concerning NaNs according // to the "Precision and Operation of SPIR-V Instructions" section of the Vulkan // specification. // clang-format off INSTANTIATE_TEST_CASE_P(FloatConstantFoldingTest, FloatInstructionFoldingTest, ::testing::Values( // Test case 0: Fold 2.0 - 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFSub %float %float_2 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, 1.0), // Test case 1: Fold 2.0 + 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFAdd %float %float_2 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, 3.0), // Test case 2: Fold 3.0 * 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFMul %float %float_3 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, 6.0), // Test case 3: Fold 1.0 / 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFDiv %float %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0.5), // Test case 4: Fold 1.0 / 0.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFDiv %float %float_1 %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, std::numeric_limits
::infinity()), // Test case 5: Fold -1.0 / 0.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFDiv %float %float_n1 %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, -std::numeric_limits
::infinity()), // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpDot %float %v2float_2_3 %v2float_2_0p5\n" + "OpReturn\n" + "OpFunctionEnd", 2, 5.5f), // Test case 7: Fold (0.0, 0.0) dot v InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%v = OpVariable %_ptr_v2float Function\n" + "%2 = OpLoad %v2float %v\n" + "%3 = OpDot %float %v2float_0_0 %2\n" + "OpReturn\n" + "OpFunctionEnd", 3, 0.0f), // Test case 8: Fold v dot (0.0, 0.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%v = OpVariable %_ptr_v2float Function\n" + "%2 = OpLoad %v2float %v\n" + "%3 = OpDot %float %2 %v2float_0_0\n" + "OpReturn\n" + "OpFunctionEnd", 3, 0.0f), // Test case 9: Fold Null dot v InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%v = OpVariable %_ptr_v2float Function\n" + "%2 = OpLoad %v2float %v\n" + "%3 = OpDot %float %v2float_null %2\n" + "OpReturn\n" + "OpFunctionEnd", 3, 0.0f), // Test case 10: Fold v dot Null InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%v = OpVariable %_ptr_v2float Function\n" + "%2 = OpLoad %v2float %v\n" + "%3 = OpDot %float %2 %v2float_null\n" + "OpReturn\n" + "OpFunctionEnd", 3, 0.0f), // Test case 11: Fold -2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFNegate %float %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, -2) )); // clang-format on using DoubleInstructionFoldingTest = ::testing::TestWithParam
>; TEST_P(DoubleInstructionFoldingTest, Case) { const auto& tc = GetParam(); // Build module. std::unique_ptr
context = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); ASSERT_NE(nullptr, context); // Fold the instruction to test. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold); bool succeeded = context->get_instruction_folder().FoldInstruction(inst); // Make sure the instruction folded as expected. EXPECT_TRUE(succeeded); if (inst != nullptr) { EXPECT_EQ(inst->opcode(), SpvOpCopyObject); inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0)); EXPECT_EQ(inst->opcode(), SpvOpConstant); analysis::ConstantManager* const_mrg = context->get_constant_mgr(); const analysis::FloatConstant* result = const_mrg->GetConstantFromInst(inst)->AsFloatConstant(); EXPECT_NE(result, nullptr); if (result != nullptr) { EXPECT_EQ(result->GetDoubleValue(), tc.expected_result); } } } // clang-format off INSTANTIATE_TEST_CASE_P(DoubleConstantFoldingTest, DoubleInstructionFoldingTest, ::testing::Values( // Test case 0: Fold 2.0 - 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFSub %double %double_2 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, 1.0), // Test case 1: Fold 2.0 + 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFAdd %double %double_2 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, 3.0), // Test case 2: Fold 3.0 * 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFMul %double %double_3 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, 6.0), // Test case 3: Fold 1.0 / 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFDiv %double %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0.5), // Test case 4: Fold 1.0 / 0.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFDiv %double %double_1 %double_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, std::numeric_limits
::infinity()), // Test case 5: Fold -1.0 / 0.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFDiv %double %double_n1 %double_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, -std::numeric_limits
::infinity()), // Test case 6: Fold (2.0, 3.0) dot (2.0, 0.5) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpDot %double %v2double_2_3 %v2double_2_0p5\n" + "OpReturn\n" + "OpFunctionEnd", 2, 5.5f), // Test case 7: Fold (0.0, 0.0) dot v InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%v = OpVariable %_ptr_v2double Function\n" + "%2 = OpLoad %v2double %v\n" + "%3 = OpDot %double %v2double_0_0 %2\n" + "OpReturn\n" + "OpFunctionEnd", 3, 0.0f), // Test case 8: Fold v dot (0.0, 0.0) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%v = OpVariable %_ptr_v2double Function\n" + "%2 = OpLoad %v2double %v\n" + "%3 = OpDot %double %2 %v2double_0_0\n" + "OpReturn\n" + "OpFunctionEnd", 3, 0.0f), // Test case 9: Fold Null dot v InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%v = OpVariable %_ptr_v2double Function\n" + "%2 = OpLoad %v2double %v\n" + "%3 = OpDot %double %v2double_null %2\n" + "OpReturn\n" + "OpFunctionEnd", 3, 0.0f), // Test case 10: Fold v dot Null InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%v = OpVariable %_ptr_v2double Function\n" + "%2 = OpLoad %v2double %v\n" + "%3 = OpDot %double %2 %v2double_null\n" + "OpReturn\n" + "OpFunctionEnd", 3, 0.0f), // Test case 11: Fold -2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFNegate %double %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, -2) )); // clang-format on // clang-format off INSTANTIATE_TEST_CASE_P(DoubleOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest, ::testing::Values( // Test case 0: fold 1.0 == 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdEqual %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 1: fold 1.0 != 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdNotEqual %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 2: fold 1.0 < 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThan %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 3: fold 1.0 > 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThan %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 4: fold 1.0 <= 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThanEqual %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 5: fold 1.0 >= 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 6: fold 1.0 == 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdEqual %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 7: fold 1.0 != 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdNotEqual %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 8: fold 1.0 < 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThan %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 9: fold 1.0 > 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThan %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 10: fold 1.0 <= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThanEqual %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 11: fold 1.0 >= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThanEqual %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 12: fold 2.0 < 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThan %bool %double_2 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 13: fold 2.0 > 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThan %bool %double_2 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 14: fold 2.0 <= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThanEqual %bool %double_2 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 15: fold 2.0 >= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThanEqual %bool %double_2 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true) )); INSTANTIATE_TEST_CASE_P(DoubleUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest, ::testing::Values( // Test case 0: fold 1.0 == 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordEqual %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 1: fold 1.0 != 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordNotEqual %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 2: fold 1.0 < 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThan %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 3: fold 1.0 > 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThan %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 4: fold 1.0 <= 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThanEqual %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 5: fold 1.0 >= 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 6: fold 1.0 == 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordEqual %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 7: fold 1.0 != 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordNotEqual %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 8: fold 1.0 < 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThan %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 9: fold 1.0 > 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThan %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 10: fold 1.0 <= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThanEqual %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 11: fold 1.0 >= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThanEqual %bool %double_1 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 12: fold 2.0 < 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThan %bool %double_2 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 13: fold 2.0 > 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThan %bool %double_2 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 14: fold 2.0 <= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThanEqual %bool %double_2 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 15: fold 2.0 >= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThanEqual %bool %double_2 %double_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true) )); INSTANTIATE_TEST_CASE_P(FloatOrderedCompareConstantFoldingTest, BooleanInstructionFoldingTest, ::testing::Values( // Test case 0: fold 1.0 == 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdEqual %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 1: fold 1.0 != 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdNotEqual %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 2: fold 1.0 < 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThan %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 3: fold 1.0 > 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThan %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 4: fold 1.0 <= 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThanEqual %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 5: fold 1.0 >= 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 6: fold 1.0 == 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdEqual %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 7: fold 1.0 != 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdNotEqual %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 8: fold 1.0 < 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThan %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 9: fold 1.0 > 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThan %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 10: fold 1.0 <= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThanEqual %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 11: fold 1.0 >= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThanEqual %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 12: fold 2.0 < 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThan %bool %float_2 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 13: fold 2.0 > 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThan %bool %float_2 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 14: fold 2.0 <= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdLessThanEqual %bool %float_2 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 15: fold 2.0 >= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdGreaterThanEqual %bool %float_2 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true) )); INSTANTIATE_TEST_CASE_P(FloatUnorderedCompareConstantFoldingTest, BooleanInstructionFoldingTest, ::testing::Values( // Test case 0: fold 1.0 == 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordEqual %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 1: fold 1.0 != 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordNotEqual %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 2: fold 1.0 < 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThan %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 3: fold 1.0 > 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThan %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 4: fold 1.0 <= 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThanEqual %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 5: fold 1.0 >= 2.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_2\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 6: fold 1.0 == 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordEqual %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 7: fold 1.0 != 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordNotEqual %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 8: fold 1.0 < 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThan %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 9: fold 1.0 > 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThan %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 10: fold 1.0 <= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThanEqual %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 11: fold 1.0 >= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThanEqual %bool %float_1 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 12: fold 2.0 < 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThan %bool %float_2 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 13: fold 2.0 > 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThan %bool %float_2 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 14: fold 2.0 <= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordLessThanEqual %bool %float_2 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 15: fold 2.0 >= 1.0 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordGreaterThanEqual %bool %float_2 %float_1\n" + "OpReturn\n" + "OpFunctionEnd", 2, true) )); INSTANTIATE_TEST_CASE_P(DoubleNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest, ::testing::Values( // Test case 0: fold NaN == 0 (ord) InstructionFoldingCase
( HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdEqual %bool %double_nan %double_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 1: fold NaN == NaN (unord) InstructionFoldingCase
( HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordEqual %bool %double_nan %double_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 2: fold NaN != NaN (ord) InstructionFoldingCase
( HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdNotEqual %bool %double_nan %double_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 3: fold NaN != NaN (unord) InstructionFoldingCase
( HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordNotEqual %bool %double_nan %double_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, true) )); INSTANTIATE_TEST_CASE_P(FloatNaNCompareConstantFoldingTest, BooleanInstructionFoldingTest, ::testing::Values( // Test case 0: fold NaN == 0 (ord) InstructionFoldingCase
( HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdEqual %bool %float_nan %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 1: fold NaN == NaN (unord) InstructionFoldingCase
( HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordEqual %bool %float_nan %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, true), // Test case 2: fold NaN != NaN (ord) InstructionFoldingCase
( HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFOrdNotEqual %bool %float_nan %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, false), // Test case 3: fold NaN != NaN (unord) InstructionFoldingCase
( HeaderWithNaN() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%2 = OpFUnordNotEqual %bool %float_nan %float_0\n" + "OpReturn\n" + "OpFunctionEnd", 2, true) )); // clang-format on template
struct InstructionFoldingCaseWithMap { InstructionFoldingCaseWithMap(const std::string& tb, uint32_t id, ResultType result, std::function
map) : test_body(tb), id_to_fold(id), expected_result(result), id_map(map) {} std::string test_body; uint32_t id_to_fold; ResultType expected_result; std::function
id_map; }; using IntegerInstructionFoldingTestWithMap = ::testing::TestWithParam
>; TEST_P(IntegerInstructionFoldingTestWithMap, Case) { const auto& tc = GetParam(); // Build module. std::unique_ptr
context = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); ASSERT_NE(nullptr, context); // Fold the instruction to test. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold); inst = context->get_instruction_folder().FoldInstructionToConstant(inst, tc.id_map); // Make sure the instruction folded as expected. EXPECT_NE(inst, nullptr); if (inst != nullptr) { EXPECT_EQ(inst->opcode(), SpvOpConstant); analysis::ConstantManager* const_mrg = context->get_constant_mgr(); const analysis::IntConstant* result = const_mrg->GetConstantFromInst(inst)->AsIntConstant(); EXPECT_NE(result, nullptr); if (result != nullptr) { EXPECT_EQ(result->GetU32BitValue(), tc.expected_result); } } } // clang-format off INSTANTIATE_TEST_CASE_P(TestCase, IntegerInstructionFoldingTestWithMap, ::testing::Values( // Test case 0: fold %3 = 0; %3 * n InstructionFoldingCaseWithMap
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load = OpLoad %int %n\n" + "%3 = OpCopyObject %int %int_0\n" "%2 = OpIMul %int %3 %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0, [](uint32_t id) {return (id == 3 ? INT_0_ID : id);}) )); // clang-format on using BooleanInstructionFoldingTestWithMap = ::testing::TestWithParam
>; TEST_P(BooleanInstructionFoldingTestWithMap, Case) { const auto& tc = GetParam(); // Build module. std::unique_ptr
context = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); ASSERT_NE(nullptr, context); // Fold the instruction to test. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold); inst = context->get_instruction_folder().FoldInstructionToConstant(inst, tc.id_map); // Make sure the instruction folded as expected. EXPECT_NE(inst, nullptr); if (inst != nullptr) { std::vector
bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse}; EXPECT_THAT(bool_opcodes, Contains(inst->opcode())); analysis::ConstantManager* const_mrg = context->get_constant_mgr(); const analysis::BoolConstant* result = const_mrg->GetConstantFromInst(inst)->AsBoolConstant(); EXPECT_NE(result, nullptr); if (result != nullptr) { EXPECT_EQ(result->value(), tc.expected_result); } } } // clang-format off INSTANTIATE_TEST_CASE_P(TestCase, BooleanInstructionFoldingTestWithMap, ::testing::Values( // Test case 0: fold %3 = true; %3 || n InstructionFoldingCaseWithMap
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_bool Function\n" + "%load = OpLoad %bool %n\n" + "%3 = OpCopyObject %bool %true\n" + "%2 = OpLogicalOr %bool %3 %load\n" + "OpReturn\n" + "OpFunctionEnd", 2, true, [](uint32_t id) {return (id == 3 ? TRUE_ID : id);}) )); // clang-format on using GeneralInstructionFoldingTest = ::testing::TestWithParam
>; TEST_P(GeneralInstructionFoldingTest, Case) { const auto& tc = GetParam(); // Build module. std::unique_ptr
context = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, tc.test_body, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); ASSERT_NE(nullptr, context); // Fold the instruction to test. analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold); std::unique_ptr
original_inst(inst->Clone(context.get())); bool succeeded = context->get_instruction_folder().FoldInstruction(inst); // Make sure the instruction folded as expected. EXPECT_EQ(inst->result_id(), original_inst->result_id()); EXPECT_EQ(inst->type_id(), original_inst->type_id()); EXPECT_TRUE((!succeeded) == (tc.expected_result == 0)); if (succeeded) { EXPECT_EQ(inst->opcode(), SpvOpCopyObject); EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result); } else { EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands()); for (uint32_t i = 0; i < inst->NumInOperands(); ++i) { EXPECT_EQ(inst->GetOperand(i), original_inst->GetOperand(i)); } } } // clang-format off INSTANTIATE_TEST_CASE_P(IntegerArithmeticTestCases, GeneralInstructionFoldingTest, ::testing::Values( // Test case 0: Don't fold n * m InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%m = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%load_m = OpLoad %int %m\n" + "%2 = OpIMul %int %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 1: Don't fold n / m (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%m = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%load_m = OpLoad %uint %m\n" + "%2 = OpUDiv %uint %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 2: Don't fold n / m (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%m = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%load_m = OpLoad %int %m\n" + "%2 = OpSDiv %int %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 3: Don't fold n remainder m InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%m = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%load_m = OpLoad %int %m\n" + "%2 = OpSRem %int %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 4: Don't fold n % m (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%m = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%load_m = OpLoad %int %m\n" + "%2 = OpSMod %int %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 5: Don't fold n % m (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%m = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%load_m = OpLoad %uint %m\n" + "%2 = OpUMod %int %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 6: Don't fold n << m InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%m = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%load_m = OpLoad %uint %m\n" + "%2 = OpShiftRightLogical %int %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 7: Don't fold n >> m InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%m = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%load_m = OpLoad %uint %m\n" + "%2 = OpShiftLeftLogical %int %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 8: Don't fold n | m InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%m = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%load_m = OpLoad %uint %m\n" + "%2 = OpBitwiseOr %int %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 9: Don't fold n & m InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%m = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%load_m = OpLoad %uint %m\n" + "%2 = OpBitwiseAnd %int %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 10: Don't fold n < m (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%m = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%load_m = OpLoad %uint %m\n" + "%2 = OpULessThan %bool %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 11: Don't fold n > m (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%m = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%load_m = OpLoad %uint %m\n" + "%2 = OpUGreaterThan %bool %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 12: Don't fold n <= m (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%m = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%load_m = OpLoad %uint %m\n" + "%2 = OpULessThanEqual %bool %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 13: Don't fold n >= m (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%m = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%load_m = OpLoad %uint %m\n" + "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 14: Don't fold n < m (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%m = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%load_m = OpLoad %int %m\n" + "%2 = OpULessThan %bool %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 15: Don't fold n > m (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%m = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%load_m = OpLoad %int %m\n" + "%2 = OpUGreaterThan %bool %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 16: Don't fold n <= m (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%m = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%load_m = OpLoad %int %m\n" + "%2 = OpULessThanEqual %bool %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 17: Don't fold n >= m (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%m = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%load_m = OpLoad %int %m\n" + "%2 = OpUGreaterThanEqual %bool %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 18: Don't fold n || m InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_bool Function\n" + "%m = OpVariable %_ptr_bool Function\n" + "%load_n = OpLoad %bool %n\n" + "%load_m = OpLoad %bool %m\n" + "%2 = OpLogicalOr %bool %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 19: Don't fold n && m InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_bool Function\n" + "%m = OpVariable %_ptr_bool Function\n" + "%load_n = OpLoad %bool %n\n" + "%load_m = OpLoad %bool %m\n" + "%2 = OpLogicalAnd %bool %load_n %load_m\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 20: Don't fold n * 3 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%2 = OpIMul %int %load_n %int_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 21: Don't fold n / 3 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%2 = OpUDiv %uint %load_n %uint_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 22: Don't fold n / 3 (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%2 = OpSDiv %int %load_n %int_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 23: Don't fold n remainder 3 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%2 = OpSRem %int %load_n %int_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 24: Don't fold n % 3 (signed) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_int Function\n" + "%load_n = OpLoad %int %n\n" + "%2 = OpSMod %int %load_n %int_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 25: Don't fold n % 3 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%2 = OpUMod %int %load_n %int_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 26: Don't fold n << 3 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%2 = OpShiftRightLogical %int %load_n %int_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 27: Don't fold n >> 3 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%2 = OpShiftLeftLogical %int %load_n %int_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 28: Don't fold n | 3 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%2 = OpBitwiseOr %int %load_n %int_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 29: Don't fold n & 3 InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%2 = OpBitwiseAnd %uint %load_n %uint_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 30: Don't fold n < 3 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%2 = OpULessThan %bool %load_n %uint_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 31: Don't fold n > 3 (unsigned) InstructionFoldingCase
( Header() + "%main = OpFunction %void None %void_func\n" + "%main_lab = OpLabel\n" + "%n = OpVariable %_ptr_uint Function\n" + "%load_n = OpLoad %uint %n\n" + "%2 = OpUGreaterThan %bool %load_n %uint_3\n" + "OpReturn\n" + "OpFunctionEnd", 2, 0), // Test case 32: Don't fold n <= 3 (unsigned) InstructionFoldingCase